Rust is a multi-paradigm, general-purpose language designed for performance, safety, and safe concurrency. Rust is syntactically similar to C++, but can guarantee memory safety. In Rust there are 2 modes of writing code, Safe Rust and Unsafe Rust.

Popular New Releases in Rust

deno

v1.20.6

rust

Rust 1.60.0

alacritty

Alacritty Version 0.10.1

tauri

tauri-driver v0.1.2

bat

v0.20.0

Popular Libraries in Rust

996.ICU

by 996icu doticonrustdoticon

star image 258630 doticonNOASSERTION

Repo for counting stars and contributing. Press F to pay respect to glorious developers.

deno

by denoland doticonrustdoticon

star image 81698 doticonMIT

A modern runtime for JavaScript and TypeScript.

rust

by rust-lang doticonrustdoticon

star image 65482 doticonNOASSERTION

Empowering everyone to build reliable and efficient software.

alacritty

by alacritty doticonrustdoticon

star image 37538 doticonApache-2.0

A cross-platform, OpenGL terminal emulator.

tauri

by tauri-apps doticonrustdoticon

star image 36698 doticonApache-2.0

Build smaller, faster, and more secure desktop applications with a web frontend.

bat

by sharkdp doticonrustdoticon

star image 33294 doticonNOASSERTION

A cat(1) clone with wings.

ripgrep

by BurntSushi doticonrustdoticon

star image 27048 doticonNOASSERTION

ripgrep recursively searches directories for a regex pattern while respecting your gitignore

meilisearch

by meilisearch doticonrustdoticon

star image 25990 doticonMIT

Powerful, fast, and an easy to use search engine

starship

by starship doticonrustdoticon

star image 24749 doticonISC

☄🌌️ The minimal, blazing-fast, and infinitely customizable prompt for any shell!

Trending New libraries in Rust

AppFlowy

by AppFlowy-IO doticonrustdoticon

star image 20428 doticonAGPL-3.0

AppFlowy is an open-source alternative to Notion. You are in charge of your data and customizations. Built with Flutter and Rust.

tools

by rome doticonrustdoticon

star image 18488 doticonMIT

The Rome Toolchain. A linter, compiler, bundler, and more for JavaScript, TypeScript, HTML, Markdown, and CSS.

appflowy

by AppFlowy-IO doticonrustdoticon

star image 16821 doticonAGPL-3.0

AppFlowy is an open-source alternative to Notion. You are in charge of your data and customizations. Built with Flutter and Rust.

bevy

by bevyengine doticonrustdoticon

star image 15512 doticonNOASSERTION

A refreshingly simple data-driven game engine built in Rust

rustdesk

by rustdesk doticonrustdoticon

star image 11657 doticonGPL-3.0

Yet another remote desktop software

helix

by helix-editor doticonrustdoticon

star image 8142 doticonMPL-2.0

A post-modern modal text editor.

gitui

by extrawurst doticonrustdoticon

star image 7791 doticonMIT

Blazing 💥 fast terminal-ui for git written in rust 🦀

czkawka

by qarmin doticonrustdoticon

star image 6600 doticonNOASSERTION

Multi functional app to find duplicates, empty folders, similar images etc.

RustScan

by RustScan doticonrustdoticon

star image 6109 doticonGPL-3.0

🤖 The Modern Port Scanner 🤖

Top Authors in Rust

1

paritytech

119 Libraries

star icon21460

2

hdhoang

107 Libraries

star icon4

3

softprops

103 Libraries

star icon2802

4

sile

96 Libraries

star icon1179

5

pop-os

88 Libraries

star icon4414

6

GaiaWorld

87 Libraries

star icon12

7

PistonDevelopers

86 Libraries

star icon12617

8

oovm

86 Libraries

star icon134

9

nathanfaucett

78 Libraries

star icon34

10

rust-lang

78 Libraries

star icon171439

1

119 Libraries

star icon21460

2

107 Libraries

star icon4

3

103 Libraries

star icon2802

4

96 Libraries

star icon1179

5

88 Libraries

star icon4414

6

87 Libraries

star icon12

7

86 Libraries

star icon12617

8

86 Libraries

star icon134

9

78 Libraries

star icon34

10

78 Libraries

star icon171439

Trending Kits in Rust

Regular expressions are useful tools for text manipulation and pattern matching. They consist of a combination of literal characters and metacharacters.  

Regex metacharacters are special characters with a symbolic meaning in regular expressions. These metacharacters have a specific function or purpose within a regular expression pattern.  

  

Example of Regex:   

  • ^ and $ anchor the regex at the start and end of the string, ensuring the entire string matches the pattern.  
  • [a-zA-Z0-9._%+-]+ matches the username part, allowing alphanumeric characters, dots, underscores, etc.  
  • @ is a literal character that must be present in the middle.  
  • [a-zA-Z0-9.-]+ matches the domain part before the dot. This allows alphanumeric characters and dots.  
  • \. is used to match a literal dot before the top-level domain (TLD).  
  • [a-zA-Z]{2,} matches the TLD, requiring at least two alphabetical characters.  

  

In conclusion, regular expressions play a vital role in text processing and manipulation. Understanding regex provides a powerful task for the beginner or an experienced developer. Regex skill is particularly crucial in Python. It serves as a versatile and expressive mechanism for working with strings.  

 

Fig: Preview of the output that you will get on running this code from your IDE.

Code


In this solution we are using Regex library of Python.

Instructions


Follow the steps carefully to get the output easily.


  1. Download and Install the PyCharm Community Edition on your computer.
  2. Open the terminal and install the required libraries with the following commands.
  3. Install Regex - pip install Regex.
  4. Create a new Python file on your IDE.
  5. Copy the snippet using the 'copy' button and paste it into your Python file.
  6. Run the current file to generate the output.


I hope you found this useful.


I found this code snippet by searching for 'python regex escaping meta characters among delimiters' in Kandi. You can try any such use case!


Environment Tested


I tested this solution in the following versions. Be mindful of changes when working with other versions.

  1. PyCharm Community Edition 2023.2
  2. The solution is created in Python 3.8 Version
  3. Regex 2023.10.3 Version.


Using this solution, we can be able to use metacharacters in python regex with simple steps. This process also facilities an easy way to use, hassle-free method to create a hands-on working version of code which would help us to use metacharacters in python regex.

Dependent Library


You can search for any dependent library on kandi like 'regex'.

FAQ 

1. What are the Python regular expressions, and why are they important?  

Python regular expressions, often referred to as regex or re are a powerful and flexible tool. Regular expressions are patterns that describe string sets. The Python re-module provides a set of functions to work with regular expressions. It allows developers to perform various text-processing tasks.  

  • Pattern Matching  
  • Text Validation  
  • String Manipulation  
  • Search and Extraction  
  • Complex Text Processing  
  • Cross-Language Compatibility  
  • Debugging and Troubleshooting  

  

2. How do string literals work in Python when it comes to regex metacharacters?  

Python string literals are a sequence of characters enclosed in quotes. Single quotes or double quotes define them. In Python, string literals are immutable and help with regular expressions. Patterns in strings are matched using regular expressions.  

  

3. What is the best way to learn Python for those new to regex metacharacters?  

The regular expressions and their metacharacters can seem challenging to its right. It becomes an essential and powerful skill for text processing in Python.  

  • Understand the Basics  
  • Start with Simple Patterns  
  • Learn Character Classes  
  • Quantifiers and Wildcards  
  • Anchors and Boundaries  
  • Grouping and Capturing  
  • Escape Metacharacters  
  • Practice Regularly  
  • Use Learning Resources  
  • Work on Real-World Examples  

  

4. What role do escape sequences play in Python regular expression matching?  

The sequences play a crucial role in Python regular expression matching. They help to handle special characters and metacharacters within regex patterns. Regular expressions of certain characters have special meanings and escape these characters. This is especially important in Python, where the backslash is also used as an escape literal.  

  

5. What occurs while using the zero or more occurrences symbol in a Python regex pattern? 

The zero or more occurrences symbol works inside a regular expression pattern. The quantifier specifies that the preceding character or group may appear zero. It allows for flexibility in matching patterns that have variable repetition.  

 

 

Support


  1. For any support on kandi solution kits, please use the chat
  2. For further learning resources, visit the Open Weaver Community learning page


Regular expressions are a useful tool for matching patterns in strings. The re-module provides support for regular expressions.


Regular expressions are a concise and flexible means for matching strings of text. It is such as particular characters, words, or patterns of characters.  

  

Key Concepts of Python Regex:  

1.Pattern: A regular expression pattern is a text string describing a search pattern. It can include literal characters, metacharacters, and various special sequences.  

2.Metacharacters: These are characters with a special meaning. Some common metacharacters.  

  • . (dot): Matches any character except a newline.  
  • ^: Anchors the regex at the start of the string.  
  • $: Anchors the regex at the end of the string.  
  • *: Represents 0 or more occurrences of previous character. 
  • +: Denotes 1 or more occurrences of the previous character. 
  • ?: Represents 0 or 1 occurrence of the preceding character. 
  • \: Escapes a metacharacter, allowing you to match it as a literal.  

3.Character Classes: Character classes allow you to match any one of a set of characters.   

  •  example, [aeiou] matches any vowel.  

4.Quantifiers: Quantifiers specify the number of occurrences of a character or group.   

  • Examples include * (0 or more), + (1 or more), and {n} (exactly n).  

5.Groups and Capturing: Parentheses () creates groups. They can also capture portions of the matched text.   

  • For example, (ab)+ would match "ab," "abab," etc., and (a)(b) would capture "a" and "b" separately.  

6.Special Sequences: These are backslash-escaped sequences that have a special meaning.   

  • For example, \d matches any digit, \w matches any alphanumeric character, and \s matches.  

  

In summary, regex is a fundamental tool for text processing and manipulation. It offers developers a concise and powerful means to work with patterns in textual data. It makes it an indispensable part of a programmer's toolkit. Understanding and mastering regular expressions can significantly enhance one's ability to work.  

  

Fig: Preview of the output that you will get on running this code from your IDE.

Code


In this solution we are using Regex library of Python.

Instructions


Follow the steps carefully to get the output easily.


  1. Download and Install the PyCharm Community Edition on your computer.
  2. Open the terminal and install the required libraries with the following commands.
  3. Install Pyglet - pip install Pyglet.
  4. Create a new Python file on your IDE.
  5. Copy the snippet using the 'copy' button and paste it into your Python file.
  6. Remove only 24 and 29 lines from the code.
  7. Run the current file to generate the output.


I hope you found this useful.


I found this code snippet by searching for 'Searching a string with a Regex in Python' in Kandi. You can try any such use case!

Environment Tested


I tested this solution in the following versions. Be mindful of changes when working with other versions.

  1. PyCharm Community Edition 2023.2
  2. The solution is created in Python 3.8 Version
  3. Regex 2023.10.3 Version.


Using this solution, we can be able to use search function in python regex with simple steps. This process also facilities an easy way to use, hassle-free method to create a hands-on working version of code which would help us to use search function in python regex.

Dependent Library


You can search for any dependent library on kandi like 'regex'.

FAQ 

1. What are regular expression patterns and how do they work in Python Re search?  

Regular expression patterns are sequences of characters that define a search pattern. These patterns can include both literal characters and special characters. In Python, regular expression patterns are often used with the re module for searching it.  

  

2. How does a regular Python string differ from pattern matches in Python Re search?  

Regular Python string literals and regular expression patterns used in Python's re modules.  

  • Escaping  
  • Raw String Literal  
  • Metacharacters  
  • Quantifiers and Special Sequences  

  

3. What are identifiers, and how do they help parse data when using Python Re search?  

The identifiers are names given to entities like variables, functions, classes, and modules.  

  • It must start with a letter (a-z, A-Z) or an underscore (_).  
  • The remaining characters can be letters, digits (0-9), or underscores.  
  • Identifiers are case-sensitive (myVar and myvar are different).  

  

4. How does the last matched capturing group refine results in Python Re search?  

The regular expression pattern contains many capturing groups. It can access the text matched by the last capturing group. It does this using the special identifier \g<index> within the pattern itself.  

  • (\w+): Matches and captures one or more-word characters (letters, digits, or underscores).  
  • -: Matches a hyphen.  
  • (\d+): Matches and captures one or more digits.  
  • -: Matches another hyphen.  
  • (\w+): Matches and captures one or more-word characters.  

  

5. What are effective tips for optimizing parser functions in Python Re search programs??  

Creating efficient parser functions using Python's re module. This involves a combination of good practices, optimization techniques, and understanding regular expressions.  

  • Regular Expressions  
  • Raw String Literals  
  • Limit Greedy Quantifiers  
  • Optimize Character Classes  
  • Avoid Backtracking  
  • Grouping and Capturing  
  • Named Capturing Groups  
  • Profiling and Testing  
  • Third-Party Libraries  

Support


  1. For any support on kandi solution kits, please use the chat
  2. For further learning resources, visit the Open Weaver Community learning page


Web3 has the underpinnings to provide for a genuinely democratic and privacy-focused World Wide Web! The early web was democratic and provided unprecedented access to information. However, given the nascent state, it was highly disorganized and provided inconsistent collaboration experiences. This led to the evolution of hyper-scale providers in Web 2.0, which brought in organization, and exciting ways of social and mobile collaboration. The downside of Web 2.0 is a very disproportionate imbalance in power resting with the big tech and social media companies and zero control with the consumers, who surprisingly are the content and data creators. These global concerns around the absolute dominance of tech platforms over consumers and privacy are driving Web 3. The core concepts of Web 3 that I found most defining are 1. A fully decentralized web, based on blockchain principles 2. The users generate tokens and in many ways are empowered to influence the platform 3. The users own and control their data While the Web 3.0 concept is a continuous work in progress, the recent focus on control, privacy, and the general prevalence of blockchain are making it closer to reality. Get ready and get started! The kandi kit on Getting Started with Web3 showcases Web3 libraries to interface with the blockchain easily.

Web3 Starter Libraries

re.split is a function in Python's re module that allows you to split a string based on a specified pattern. It uses a RE to define the splitting pattern.

It relies on a fixed delimiter. re.split is useful for cases to split strings using a pattern that goes beyond a simple fixed delimiter. It provides more flexibility in handling variations within the text. re.split() in Python is a method for splitting strings using a regular expression pattern.  

Here are some common use cases:  

  • Splitting Strings into Lines  
  • Splitting by Many Delimiters  
  • Splitting Files into Chunks  
  • Limiting the Number of Splits  
  • Using Capture Groups  
  • Removing Empty Strings  

When splitting strings, various options are available, each suited for different scenarios.  

Here are a few methods:  

  • Using Default Delimiter: The simplest method involves splitting a string. This occurs using a default delimiter, such as a space or comma. 
  • Delimiter-Based Splitting: Specify a custom delimiter to split the string. Useful when the data has a consistent pattern.  
  • Regular Expressions (Regex): Regex provides powerful pattern matching for string splitting.  
  • Whitespace Splitting: Splits the string based on whitespace characters (spaces, tabs, line breaks).  
  • Limiting the Number of Splits: Some languages allow you to limit the number of splits. It provides control over the output.  
  • Partition Method: It splits a string into three parts based on a delimiter.  
  • Strtok Function: In languages like C or C++, this helps in splitting strings based on a delimiter.  
  • Splitting Lines: Often used for processing text files. It splits a string into lines using newline characters.  
  • Joining and Splitting: It allows for more complex operations. Those operations reverse the order of elements.  
  • CSV Parsing: Specific to handling CSV data. Used libraries like csv in Python provide convenient methods for parsing.  

When using re.split in Python, consider these tips:  

  • Choose the Right Delimiter  
  • Escape Special Characters  
  • Handle Many Delimiters  
  • Consider Whitespace  
  • Handle Repetitive Delimiters  
  • Account for Leading and Trailing Delimiters  
  • Be Mindful of Empty Strings  
  • Use Non-Capturing Groups  
  • Test with Edge Cases  
  • Consider Alternative Approaches  

In conclusion, Python's re.split offers enhanced string-splitting capabilities. It enables more sophisticated and flexible text processing. Its regex-based approach allows for precise pattern matching, facilitating complex parsing tasks. This can lead to cleaner, more efficient code, improved readability, and better maintenance. Embracing re.split empowers developers to handle diverse input scenarios with ease. This makes it a valuable tool for robust and adaptable codebases.  

Fig: Preview of the output that you will get on running this code from your IDE.

Code

In this solution we are using regex library in Python.

Instructions

Follow the steps carefully to get the output easily.


  1. Download and Install the PyCharm Community Edition on your computer.
  2. Open the terminal and install the required libraries with the following commands.
  3. Create a new Python file on your IDE.
  4. Copy the snippet using the 'copy' button and paste it into your python file.
  5. Run the current file to generate the output.


I hope you found this useful.


I found this code snippet by searching for 'How to use split function in regex' in Kandi. You can try any such use case!

Environment Tested

I tested this solution in the following versions. Be mindful of changes when working with other versions.

  1. PyCharm Community Edition 2022.3.1
  2. The solution is created in Python 3.11.1 Version
  3. regex 1.0.0 Version


Using this solution, we can able to use split function in regex in python with simple steps. This process also facilities an easy way to use, hassle-free method to create a hands-on working version of code which would help us to use split function in regex in python.

Dependent Library

You can search for any dependent library on Kandi like 'regex'.

FAQ  

1. What is a regular Python string literal, and how does it impact the re.split function?  

A regular Python string literal is a sequence of characters in single (' '), double (" "), or triple ('' ''' or """ """) quotes. In the context of the re.split function, the regular string literal is the pattern. That pattern helps to identify the delimiter for splitting a string.  


2. How do I use a regular expression cache to improve performance when using re.split?  

To use this, you can compile your regular expression pattern using re.compile. This creates a compiled regular & reusable expression object. It reduces the overhead of recompiling the pattern for each split operation.  


3. What are identifiers in relation to the re.split function?  

Identifiers refer to the delimiters or patterns. It identifies where the string should split. These can be simple strings, depending on the desired splitting criteria.  


4. How can I create a compiled regular expression object to use with the re.split function?  

You can create a compiled regular expression object using the re.compile function.  

For example:   

import re   

pattern = re.compile(r'\s+')   

result = pattern.split("This is a sample string")  


5. Is the re.split function part of the Python Standard Library, or is it an external library?  

The re.split function is part of the Python Standard Library, the re module. It is not an external library, so you can use it without extra installations.  

Support

  1. For any support on Kandi solution kits, please use the chat
  2. For further learning resources, visit the Open Weaver Community learning page

Trending Discussions on Rust

Why is Rust NLL not working for multiple borrows in the same statement?

Next failed to load SWC binary

Emulate BTreeMap::pop_last in stable Rust

Match ergonomics and &amp; pattern

What is the built-in `#[main]` attribute?

Difference between `cargo doc` and `cargo rustdoc`

Unable to specify `edition2021` in order to use unstable packages in Rust

What is the idiomatic way to do something when an Option is either None, or the inner value meets some condition?

What is the official Rust guidance for interoperability with C++, in particular passing and returning structs as arguments?

Why does iteration over an inclusive range generate longer assembly in Rust?

QUESTION

Why is Rust NLL not working for multiple borrows in the same statement?

Asked 2022-Apr-12 at 00:43

First, I tried something like this:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3

It can't be compiled because:

error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable

I thought that the Rust borrow checker could be smarter than this, so I found something called NLL, and it should solve this problem.

I tried the sample:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5

It could work, but why is it not working with rotate_right? Both of them take a &mut self. What's going on?

ANSWER

Answered 2022-Apr-12 at 00:43

It is definitely an interesting one.

They are similar - but not quite the same. resize() is a member of Vec. rotate_right(), on the other hand, is a method of slices.

Vec<T> derefs to [T], so most of the time this does not matter. But actually, while this call:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6

Desugars to something like:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7

This call:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8

Is more like:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12

But in what order?

This is the MIR for rotate_right() (simplified a lot):

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17

And this is the MIR for resize() (again, simplified a lot):

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21

In the resize() example, we first call Vec::len() with a reference to vec. This returns usize. Then we call Vec::resize(), when we have no outstanding references to vec, so mutably borrowing it is fine!

However, with rotate_right(), first we call <Vec<i32> as DerefMut>::deref_mut(&mut vec). This returns &mut [i32], with its lifetime tied to vec. That is, as long as this reference (mutable reference!) is alive, we are not allowed to use have any other reference to vec. But then we try to borrow vec in order to pass the (shared, but it doesn't matter) reference to Vec::len(), while we still need to use the mutable reference from deref_mut() later, in the call to <[i32]>::rotate_right()! This is an error.

This is because Rust defines an evaluation order for operands:

Expressions taking multiple operands are evaluated left to right as written in the source code.

Because vec.resize() is actually (&mut *vec).rotate_right(), we first evaluate the dereference+reference, then the arguments:

1let mut vec = vec![0];
2vec.rotate_right(vec.len());
3let mut vec = vec![0];
4vec.resize(vec.len(), 0);
5vec.resize(vec.len(), 0);
6&lt;Vec&lt;i32&gt;&gt;::resize(&amp;mut vec, &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec), 0);
7vec.rotate_right(vec.len());
8&lt;[i32]&gt;::rotate_right(
9    &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(&amp;mut vec),
10    &lt;Vec&lt;i32&gt;&gt;::len(&amp;vec),
11);
12fn foo() -&gt; () {
13    _4 = &lt;Vec&lt;i32&gt; as DerefMut&gt;::deref_mut(move _5);
14    _6 = Vec::&lt;i32&gt;::len(move _7);
15    _2 = core::slice::&lt;impl [i32]&gt;::rotate_right(move _3, move _6);
16}
17fn foo() -&gt; () {
18    _4 = Vec::&lt;i32&gt;::len(move _5);
19    _2 = Vec::&lt;i32&gt;::resize(move _3, move _4, const 0_i32);
20}
21let dereferenced_vec = &amp;mut *vec;
22let len = vec.len();
23dereferencec_vec.rotate_right(len);
24

Which is obviously a violation of the borrow rules.

On the other hand, vec.resize(vec.len()) has no work to do on the callee (vec), and so we first evaluate vec.len(), and then the call itself.

Solving this is as easy as extracting the vec.len() to a new line (new statement, to be precise), and the compiler also suggests that.

Source https://stackoverflow.com/questions/71823410

QUESTION

Next failed to load SWC binary

Asked 2022-Mar-22 at 05:46

When trying to run the command using nextjs npm run dev shows error - failed to load SWC binary see more info here: https://nextjs.org/docs/messages/failed-loading-swc.

I've tried uninstalling node and reinstalling it again with version 16.13 but without success, on the vercel page, but unsuccessful so far. Any tips?

Also, I noticed it's a current issue on NextJS discussion page and it has to do with the new Rust-base compiler which is faster than Babel.

ANSWER

Answered 2021-Nov-20 at 13:57

This worked as suggeted by nextJS docs but it takes away Rust compiler and all its benefits... Here is what I did for those who eventually get stuck...

Step 1. add this line or edit next.json.js

1{
2swcMinify: false // it should be false by default 
3}
4

Step 2. add a ".babelrc" file to project root dir

Step 3. add this snippet to the new file ".babelrc"

1{
2swcMinify: false // it should be false by default 
3}
4{
5&quot;presets&quot;: [&quot;next/babel&quot;]
6}
7

Step 4, you need to run this command as steps 1-3 will remove SWC failed to load error but you will notice another error when you run the build command. So run this too

1{
2swcMinify: false // it should be false by default 
3}
4{
5&quot;presets&quot;: [&quot;next/babel&quot;]
6}
7npm install next@canary
8

hope this helps

Source https://stackoverflow.com/questions/69816589

QUESTION

Emulate BTreeMap::pop_last in stable Rust

Asked 2022-Mar-15 at 16:55

In the current stable Rust, is there a way to write a function equivalent to BTreeMap::pop_last?

The best I could come up with is:

1fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
2where
3    K: Ord + Clone,
4{
5    let last = m.iter().next_back();
6    if let Some((k, _)) = last {
7        let k_copy = k.clone();
8        return m.remove_entry(&amp;k_copy);
9    }
10    None
11}
12

It works, but it requires that the key is cloneable. BTreeMap::pop_last from Rust nightly imposes no such constraint.

If I remove the cloning like this

1fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
2where
3    K: Ord + Clone,
4{
5    let last = m.iter().next_back();
6    if let Some((k, _)) = last {
7        let k_copy = k.clone();
8        return m.remove_entry(&amp;k_copy);
9    }
10    None
11}
12fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
13where
14    K: Ord,
15{
16    let last = m.iter().next_back();
17    if let Some((k, _)) = last {
18        return m.remove_entry(k);
19    }
20    None
21}
22

it leads to

1fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
2where
3    K: Ord + Clone,
4{
5    let last = m.iter().next_back();
6    if let Some((k, _)) = last {
7        let k_copy = k.clone();
8        return m.remove_entry(&amp;k_copy);
9    }
10    None
11}
12fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
13where
14    K: Ord,
15{
16    let last = m.iter().next_back();
17    if let Some((k, _)) = last {
18        return m.remove_entry(k);
19    }
20    None
21}
22error[E0502]: cannot borrow `*m` as mutable because it is also borrowed as immutable
23  --&gt; ...
24   |
25.. |     let last = m.iter().next_back();
26   |                -------- immutable borrow occurs here
27.. |     if let Some((k, _)) = last {
28.. |         return m.remove_entry(k);
29   |                ^^------------^^^
30   |                | |
31   |                | immutable borrow later used by call
32   |                mutable borrow occurs here
33

Is there a way to work around this issue without imposing additional constraints on map key and value types?

ANSWER

Answered 2022-Mar-15 at 16:55

Is there a way to work around this issue without imposing additional constraints on map key and value types?

It doesn't appear doable in safe Rust, at least not with reasonable algorithmic complexity. (See Aiden4's answer for a solution that does it by re-building the whole map.)

But if you're allowed to use unsafe, and if you're determined enough that you want to delve into it, this code could do it:

1fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
2where
3    K: Ord + Clone,
4{
5    let last = m.iter().next_back();
6    if let Some((k, _)) = last {
7        let k_copy = k.clone();
8        return m.remove_entry(&amp;k_copy);
9    }
10    None
11}
12fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
13where
14    K: Ord,
15{
16    let last = m.iter().next_back();
17    if let Some((k, _)) = last {
18        return m.remove_entry(k);
19    }
20    None
21}
22error[E0502]: cannot borrow `*m` as mutable because it is also borrowed as immutable
23  --&gt; ...
24   |
25.. |     let last = m.iter().next_back();
26   |                -------- immutable borrow occurs here
27.. |     if let Some((k, _)) = last {
28.. |         return m.remove_entry(k);
29   |                ^^------------^^^
30   |                | |
31   |                | immutable borrow later used by call
32   |                mutable borrow occurs here
33// Safety: if key uses shared interior mutability, the comparison function
34// must not use it. (E.g. it is not allowed to call borrow_mut() on a
35// Rc&lt;RefCell&lt;X&gt;&gt; inside the key). It is extremely unlikely that such a
36// key exists, but it's possible to write it, so this must be marked unsafe.
37unsafe fn map_pop_last&lt;K, V&gt;(m: &amp;mut BTreeMap&lt;K, V&gt;) -&gt; Option&lt;(K, V)&gt;
38where
39    K: Ord,
40{
41    // We make a shallow copy of the key in the map, and pass a
42    // reference to the copy to BTreeMap::remove_entry(). Since
43    // remove_entry() is not dropping the key/value pair (it's returning
44    // it), our shallow copy will remain throughout the lifetime of
45    // remove_entry(), even if the key contains references.
46    let (last_key_ref, _) = m.iter().next_back()?;
47    let last_key_copy = ManuallyDrop::new(std::ptr::read(last_key_ref));
48    m.remove_entry(&amp;last_key_copy)
49}
50

Source https://stackoverflow.com/questions/71455966

QUESTION

Match ergonomics and &amp; pattern

Asked 2022-Mar-03 at 21:14

Consider following code

1fn main() {
2    let s = (&amp;&amp;0,);
3    let (x,) = s; // &amp;&amp;i32
4    let (&amp;y,) = s; // &amp;i32
5    let (&amp;&amp;z,) = s; // i32
6
7    let t = &amp;(&amp;0,);
8    let (x,) = t; // &amp;&amp;i32
9    let (&amp;y,) = t; // i32
10
11    let u = &amp;&amp;(0,);
12    let (x,) = u; // &amp;i32
13    let (&amp;y,) = u; // mismatched types expected type `{integer}` found reference `&amp;_`
14}
15

Could someone explain, why & pattern behaves differently in every case? I suppose it is tied somehow to match ergonomics, maybe some coercions come into play? But I can't wrap my head around it.

ANSWER

Answered 2022-Mar-03 at 21:14

You are correct, this is due to match ergonomics. The first case should hopefully be self explanatory, but the second and third cases can be a bit counter-intuitive.

In the second case:

  • (x,) is a non-reference pattern (see the second example in the RFC). The t tuple reference is dereferenced, and x is bound as a ref as it also is a non-reference pattern. Note that t.0 was a reference to begin with, thus resulting in x being a double reference.

  • (&y,) is also a non-reference pattern. The t tuple is dereferenced again to a (&i32,). However, &y is a reference pattern being matched to a &i32 reference. Hence y is bound with move mode and is an i32.

In the third case:

  • Using the same reasoning as the second case, u is dereferenced via Deref coercion to an (i32,), and x, a non-reference pattern, is bound in ref mode. Hence x is an &i32.

  • Again with the same reasoning as the second case, u is dereferenced to an (i32,). The &y reference pattern is then matched to an i32, a non-reference, which causes an error.

Source https://stackoverflow.com/questions/71343407

QUESTION

What is the built-in `#[main]` attribute?

Asked 2022-Feb-15 at 23:57

I have been using the #[tokio::main] macro in one of my programs. After importing main and using it unqualified, I encountered an unexpected error.

1use tokio::main;
2
3#[main]
4async fn main() {}
5
1use tokio::main;
2
3#[main]
4async fn main() {}
5error[E0659]: `main` is ambiguous
6 --&gt; src/main.rs:3:3
7  |
83 | #[main]
9  |   ^^^^ ambiguous name
10  |
11  = note: ambiguous because of a name conflict with a builtin attribute
12  = note: `main` could refer to a built-in attribute
13

I've been scouring the documentation but I haven't been able to find this built-in #[main] attribute described anywhere. The Rust Reference contains an index of built-in attributes. The index doesn't include #[main], though it does include an attribute named #[no_main].

I did a search of the rustlang/rust repository, and found some code that seems related, but it seems to use a pair of macros named #[start] and #[rustc_main], with no mention of #[main] itself. (Neither of those macros appears to be usable on stable, with #[start] emitting an error that it's unstable, and #[rustc_main] emitting an error that it's only meant for internal use by the compiler.)

My guess from the name would have been that it's meant to mark a different function as an entry-point instead of main, but it also doesn't seem to do that:

1use tokio::main;
2
3#[main]
4async fn main() {}
5error[E0659]: `main` is ambiguous
6 --&gt; src/main.rs:3:3
7  |
83 | #[main]
9  |   ^^^^ ambiguous name
10  |
11  = note: ambiguous because of a name conflict with a builtin attribute
12  = note: `main` could refer to a built-in attribute
13#[main]
14fn something_else() {
15    println!(&quot;this does not run&quot;);
16}
17
18fn main() {
19    println!(&quot;this runs&quot;);
20}
21

Rust Analyzer didn't have much to offer:

a screenshot showing Rust Analyzer's contextual help for the #[main] attribute, devoid of any details

What does the built-in #[main] attribute do, aside from conflicting with my imports? 😉

ANSWER

Answered 2022-Feb-15 at 23:57

#[main] is an old, unstable attribute that was mostly removed from the language in 1.53.0. However, the removal missed one line, with the result you see: the attribute had no effect, but it could be used on stable Rust without an error, and conflicted with imported attributes named main. This was a bug, not intended behaviour. It has been fixed as of nightly-2022-02-10 and 1.59.0-beta.8. Your example with use tokio::main; and #[main] can now run without error.

Before it was removed, the unstable #[main] was used to specify the entry point of a program. Alex Crichton described the behaviour of it and related attributes in a 2016 comment on GitHub:

Ah yes, we've got three entry points. I.. think this is how they work:

  • First, #[start], the receiver of int argc and char **argv. This is literally the symbol main (or what is called by that symbol generated in the compiler).
  • Next, there's #[lang = "start"]. If no #[start] exists in the crate graph then the compiler generates a main function that calls this. This functions receives argc/argv along with a third argument that is a function pointer to the #[main] function (defined below). Importantly, #[lang = "start"] can be located in a library. For example it's located in the standard library (libstd).
  • Finally, #[main], the main function for an executable. This is passed no arguments and is called by #[lang = "start"] (if it decides to). The standard library uses this to initialize itself and then call the Rust program. This, if not specified, defaults to fn main at the top.

So to answer your question, this isn't the same as #[start]. To answer your other (possibly not yet asked) question, yes we have too many entry points.

Source https://stackoverflow.com/questions/71024443

QUESTION

Difference between `cargo doc` and `cargo rustdoc`

Asked 2022-Feb-15 at 14:32

According to doc.rust-lang.org

build[s] a package's documentation, using specified custom flags

build[s] a package's documentation

What is the difference between the two? From what I understand cargo rustdoc is just like cargo doc, but it allows for more lints—for instance:

1#![deny(rustdoc::broken_intra_doc_links)]
2

Is this correct? Oddly enough, cargo rustdoc will also fail in certain situations where cargo doc doesn't. For instance

1#![deny(rustdoc::broken_intra_doc_links)]
2some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
3❯ cargo doc
4    Finished dev [unoptimized + debuginfo] target(s) in 0.53s
5
6some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
7❯ cargo rustdoc
8error: manifest path `some/folder/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace
9

Also, cargo doc does not support adding the -D option, whereas cargo rustdoc does.

1#![deny(rustdoc::broken_intra_doc_links)]
2some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
3❯ cargo doc
4    Finished dev [unoptimized + debuginfo] target(s) in 0.53s
5
6some/folder on some-branch [$!] via 🦀 v1.60.0-nightly
7❯ cargo rustdoc
8error: manifest path `some/folder/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace
9❯ cargo doc -- -D rustdoc::broken_intra_doc_links
10error: Found argument '-D' which wasn't expected, or isn't valid in this context
11
12USAGE:
13    cargo doc [OPTIONS]
14
15For more information try --help
16

ANSWER

Answered 2022-Jan-11 at 21:00

Their relationship is like between cargo build and cargo rustc: cargo doc performs all the usual work, for an entire workspace, including dependencies (by default). cargo rustdoc allows you to pass flags directly to rustdoc, and only works for a single crate.

Here is the execution code for cargo rustdoc. Here is the code for cargo doc. The only differences is that cargo rustdoc always specify to not check dependencies while cargo doc allows you to choose (by default it does, but you can specify the flag --no-deps), and that cargo rustc allows you to pass flags directly to rustdoc with the flags after the --.

Source https://stackoverflow.com/questions/70673143

QUESTION

Unable to specify `edition2021` in order to use unstable packages in Rust

Asked 2022-Feb-02 at 07:05

I want to run an example via Cargo but I am facing an error:

1error: failed to parse manifest at `/Users/aviralsrivastava/dev/subxt/Cargo.toml`
2

The full stacktrace is:

1error: failed to parse manifest at `/Users/aviralsrivastava/dev/subxt/Cargo.toml`
2error: failed to parse manifest at `/Users/aviralsrivastava/dev/subxt/Cargo.toml`
3
4Caused by:
5  feature `edition2021` is required
6
7  The package requires the Cargo feature called `edition2021`, but that feature is not stabilized in this version of Cargo (1.56.0-nightly (b51439fd8 2021-08-09)).
8  Consider adding `cargo-features = [&quot;edition2021&quot;]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.
9  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#edition-2021 for more information about the status of this feature.
10

Based on the suggestion, I go ahead and modify the Cargo.toml:

1error: failed to parse manifest at `/Users/aviralsrivastava/dev/subxt/Cargo.toml`
2error: failed to parse manifest at `/Users/aviralsrivastava/dev/subxt/Cargo.toml`
3
4Caused by:
5  feature `edition2021` is required
6
7  The package requires the Cargo feature called `edition2021`, but that feature is not stabilized in this version of Cargo (1.56.0-nightly (b51439fd8 2021-08-09)).
8  Consider adding `cargo-features = [&quot;edition2021&quot;]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.
9  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#edition-2021 for more information about the status of this feature.
10  Consider adding `cargo-features = [&quot;edition2021&quot;]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.
11diff --git a/Cargo.toml b/Cargo.toml
12index 26a02c7..186d09b 100644
13--- a/Cargo.toml
14+++ b/Cargo.toml
15@@ -1,6 +1,6 @@
16 [workspace]
17 members = [&quot;.&quot;, &quot;cli&quot;, &quot;codegen&quot;, &quot;macro&quot;]
18-
19+cargo-features = [&quot;edition2021&quot;]
20 [package]
21 name = &quot;subxt&quot;
22 version = &quot;0.15.0&quot;
23(END)
24

I still face the same error as if nothing was changed in the toml file.

How do I resolve the above error in order to use unstable packages?

ANSWER

Answered 2021-Dec-14 at 14:09

Update the Rust to satisfy the new edition 2021.

rustup default nightly && rustup update

Thanks to @ken. Yes, you can use the stable channel too!

But I love nightly personally.

Source https://stackoverflow.com/questions/69848319

QUESTION

What is the idiomatic way to do something when an Option is either None, or the inner value meets some condition?

Asked 2022-Jan-28 at 08:44

Is there a more idiomatic way to express something like the following?

1fn main() {
2    let mut foo: Option&lt;u8&gt; = None;
3    match foo {
4        Some(foo_val) if ! (foo_val &lt; 5) /* i.e. the negation of my acceptance condition */ =&gt; {}
5        _ =&gt; { foo.replace(5); }
6    }
7}
8

It seems like most of the time there's an alternative to having an arm that doesn't do anything, but I've been unable to find one for this particular case.

What I'd like to say is the more direct if foo.is_none() || /* some way to extract and test the inner value */ { ... }, or perhaps some chaining trick that's eluding me.

ANSWER

Answered 2022-Jan-27 at 07:32

There are many ways to do it. One of the simplest (and arguably most readable) is something like this:

1fn main() {
2    let mut foo: Option&lt;u8&gt; = None;
3    match foo {
4        Some(foo_val) if ! (foo_val &lt; 5) /* i.e. the negation of my acceptance condition */ =&gt; {}
5        _ =&gt; { foo.replace(5); }
6    }
7}
8if foo.unwrap_or(0) &lt; 5 {
9    ...
10}
11

The above will be true in both cases:

  • when foo is Some with a value smaller than 5;
  • when foo is None.

In some more complex scenarios, where the "default" value needs to be calculated and performance is critical, you might want to consider unwrap_or_else.

As Lukas suggested, the map_or method can also be used. Note that arguments passed to map_or are eagerly evaluated, so if performance is critical, you might want to consider map_or_else as an alternative.

Source https://stackoverflow.com/questions/70859478

QUESTION

What is the official Rust guidance for interoperability with C++, in particular passing and returning structs as arguments?

Asked 2022-Jan-26 at 23:08

I'm trying to adapt some layers of existing C++ code to be used by Rust and apparently the way is through a C API.

For example, one function might return a struct as an object

1#pragma pack(push,4)
2struct Result {
3    char ch;
4    int32_t sum1;
5    int32_t sum2;
6};
7#pragma pack(pop)
8
9extern &quot;C&quot;
10Result
11muladd(int32_t a, int32_t b, int32_t c) {
12    return Result{1, a+b*c, a*b+c};
13}
14

And from Rust I'm doing

1#pragma pack(push,4)
2struct Result {
3    char ch;
4    int32_t sum1;
5    int32_t sum2;
6};
7#pragma pack(pop)
8
9extern &quot;C&quot;
10Result
11muladd(int32_t a, int32_t b, int32_t c) {
12    return Result{1, a+b*c, a*b+c};
13}
14#[repr(C,align(4))]
15pub struct Result {
16    pub ch: i8,
17    pub sum1: i32,
18    pub sum2: i32,
19}
20
21extern &quot;C&quot; {
22    pub fn muladd( a:i32, b:i32, c:i32 ) -&gt; Result;
23}
24
25pub fn usemuladd( val: i32 ) -&gt; i32 {
26    unsafe {
27       let res = muladd( val, val, val );
28       return res.sum1;
29    }
30}
31

I'm seeing odd results with respect to alignment and packing of structures. I have read that Rust can play around with structs, and neither ordering or packing are guaranteed.

It seems that using #[repr(C)] and extern "C" is the key to a happy compatibility layer. My question is then: can I trust that these two will get me solid through or there will always be unannounced edge cases that I have to worry about?

https://godbolt.org/z/aEh4jKxxf

ANSWER

Answered 2022-Jan-21 at 01:15

extern "C" on both sides + #[repr(C)] on the Rust side + only using C-compatible types for interfacing between C++ and Rust, should work.

Alternatively, see cxx and autocxx.

Source https://stackoverflow.com/questions/70794769

QUESTION

Why does iteration over an inclusive range generate longer assembly in Rust?

Asked 2022-Jan-15 at 11:19

These two loops are equivalent in C++ and Rust:

1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9
1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9pub fn sum1(num: u64) -&gt; u64 {
10    let mut sum: u64 = 0;
11    for j in 0u64..=num {
12        sum += 1;
13    }
14    return sum;
15}
16

However the C++ version generates a very terse assembly:

1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9pub fn sum1(num: u64) -&gt; u64 {
10    let mut sum: u64 = 0;
11    for j in 0u64..=num {
12        sum += 1;
13    }
14    return sum;
15}
16sum1(unsigned long):                               # @sum1(unsigned long)
17        xor     eax, eax
18.LBB0_1:                                # =&gt;This Inner Loop Header: Depth=1
19        add     rax, 1
20        cmp     rax, rdi
21        jbe     .LBB0_1
22        ret
23

while Rust's version is very long with two checks in the loop instead of one:

1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9pub fn sum1(num: u64) -&gt; u64 {
10    let mut sum: u64 = 0;
11    for j in 0u64..=num {
12        sum += 1;
13    }
14    return sum;
15}
16sum1(unsigned long):                               # @sum1(unsigned long)
17        xor     eax, eax
18.LBB0_1:                                # =&gt;This Inner Loop Header: Depth=1
19        add     rax, 1
20        cmp     rax, rdi
21        jbe     .LBB0_1
22        ret
23example::sum1:
24        xor     eax, eax
25        xor     ecx, ecx
26.LBB0_1:
27        mov     rdx, rcx
28        cmp     rcx, rdi
29        adc     rcx, 0
30        add     rax, 1
31        cmp     rdx, rdi
32        jae     .LBB0_3
33        cmp     rcx, rdi
34        jbe     .LBB0_1
35.LBB0_3:
36        ret
37

Godbolt: https://godbolt.org/z/xYW94qxjK

What is Rust intrinsically trying to prevent that C++ is carefree about?

ANSWER

Answered 2022-Jan-12 at 10:20

Overflow in the iterator state.

The C++ version will loop forever when given a large enough input:

1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9pub fn sum1(num: u64) -&gt; u64 {
10    let mut sum: u64 = 0;
11    for j in 0u64..=num {
12        sum += 1;
13    }
14    return sum;
15}
16sum1(unsigned long):                               # @sum1(unsigned long)
17        xor     eax, eax
18.LBB0_1:                                # =&gt;This Inner Loop Header: Depth=1
19        add     rax, 1
20        cmp     rax, rdi
21        jbe     .LBB0_1
22        ret
23example::sum1:
24        xor     eax, eax
25        xor     ecx, ecx
26.LBB0_1:
27        mov     rdx, rcx
28        cmp     rcx, rdi
29        adc     rcx, 0
30        add     rax, 1
31        cmp     rdx, rdi
32        jae     .LBB0_3
33        cmp     rcx, rdi
34        jbe     .LBB0_1
35.LBB0_3:
36        ret
37#include &lt;cstdint&gt;
38
39[[gnu::noinline]]
40std::uint64_t sum1(std::uint64_t n) {  
41    std::uint64_t sum = 0;
42    for (std::uint64_t j = 0; j &lt;= n; ++j) {
43        sum += 1;
44    }
45    return sum;
46}
47
48#include &lt;iostream&gt;
49
50int main() {
51    std::cout &lt;&lt; sum1(UINT64_C(0xffffffff'ffffffff)) &lt;&lt; std::endl;
52
53    return 0;
54}
55

This is because when the loop counter j finally reaches 0xffffffff'ffffffff, incrementing it wraps around to 0, which means the loop invariant j <= n is always fulfilled and the loop never exits.

Strictly speaking, invoking sum1 with 0xffffffff'ffffffff infamously triggers undefined behaviour, though not because of overflow itself, but since infinite loops without externally-visible side effects are UB ([intro.progress]/1). This is why I applied the [[gnu::noinline]] attribute to the function to prevent the compiler from taking ‘advantage’ of that in optimisation passes.

The Rust version, on the other hand, is not only perfectly well-defined, but iterates exactly as many times as the cardinality of the range:

1#include &lt;cstdint&gt;
2uint64_t sum1(uint64_t n) {  
3    uint64_t sum = 0;
4    for (uint64_t j = 0; j &lt;= n; ++j) {
5        sum += 1;
6    }
7    return sum;
8}
9pub fn sum1(num: u64) -&gt; u64 {
10    let mut sum: u64 = 0;
11    for j in 0u64..=num {
12        sum += 1;
13    }
14    return sum;
15}
16sum1(unsigned long):                               # @sum1(unsigned long)
17        xor     eax, eax
18.LBB0_1:                                # =&gt;This Inner Loop Header: Depth=1
19        add     rax, 1
20        cmp     rax, rdi
21        jbe     .LBB0_1
22        ret
23example::sum1:
24        xor     eax, eax
25        xor     ecx, ecx
26.LBB0_1:
27        mov     rdx, rcx
28        cmp     rcx, rdi
29        adc     rcx, 0
30        add     rax, 1
31        cmp     rdx, rdi
32        jae     .LBB0_3
33        cmp     rcx, rdi
34        jbe     .LBB0_1
35.LBB0_3:
36        ret
37#include &lt;cstdint&gt;
38
39[[gnu::noinline]]
40std::uint64_t sum1(std::uint64_t n) {  
41    std::uint64_t sum = 0;
42    for (std::uint64_t j = 0; j &lt;= n; ++j) {
43        sum += 1;
44    }
45    return sum;
46}
47
48#include &lt;iostream&gt;
49
50int main() {
51    std::cout &lt;&lt; sum1(UINT64_C(0xffffffff'ffffffff)) &lt;&lt; std::endl;
52
53    return 0;
54}
55use std::num::Wrapping;
56
57fn sum1(num: u64) -&gt; u64 {
58    let mut sum = Wrapping(0);
59    for _ in 0..=num {
60        sum += Wrapping(1);
61    }
62    return sum.0;
63}
64
65fn main() {
66    println!(&quot;{}&quot;, sum1(0xffffffff_ffffffff));
67}
68

The above program (slightly modified to avoid getting bogged down in debug versus release mode differences with respect to the summation) will terminate after exactly 18446744073709551616 iterations and print 0; the Rust version carefully maintains iterator state so that overflow does not happen in the iterator.

Source https://stackoverflow.com/questions/70672533

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in Rust

Tutorials and Learning Resources are not available at this moment for Rust

Share this Page

share link

Get latest updates on Rust