Rust newbie here.
When providing a parameter and leaving it unused in a function declaration (e.g. when learning Rust...) the compiler warns about the fact that the variable is unused in the scope, and proposes to consider putting an underline before it. Doing so, the warning disappears.
warning: unused variable: `y`
--> src/main.rs:23:29
|
23 | fn another_function(x: i32, y: i32) {
| ^ help: consider using `_y` instead
|
= note: #[warn(unused_variables)] on by default
why? How is the variable treated differently then?
It's just a convention: Rust doesn't emit a warning if a variable whose name starts with an underscore is not used because sometimes you may need a variable that won't be used anywhere else in your code.
Related
Say you have
let x: u8 = 1
println!("{x}");
this works fine; however, if you instead have
let x: [u8; 1] = [1];
println!("{x[0]}");
then it throws the error
error: invalid format string: expected `'}'`, found `'['
|
| println!("{x[0]}");
| - ^ expected `}` in format string
| |
| because of this opening brace
|
= note: if you intended to print `{`, you can escape it using `{{`
why is this?
The inline print functionality is only intended for variable names. To be honest though, I rarely see this syntax used though. Most people prefer println!("{}", x[0]) instead, and this is one of the main reasons why.
I can defiantly see where they were coming from though. The {:?} or {:X} syntax might look weird since the colon does not seem to have a use in these statements to print in debug or hexadecimal mode, but I suspect it was made to mirror fields in structs and function arguments. It starts to look more familiar when you write it with the inline variable and spacing: format!("{name: ?}"). Under this reasoning it makes more sense to only allow idents here (Token for an identity. Essentially the name of a variable/type/module/etc). But this didn't really materialize (if it ever even was a thing) so we don't have this syntax.
Personally, I think they could have made it work, but you would end up with confusion about how :? (and other format specifiers) work in regards to expressions. For example, if people are taught that {x.foo()} will print the display of the expression x.foo() then does that mean x.foo(): ? is also a valid expression? What about -3.0:3.0?? It kinda looks like a range in python, but I have just worded it in a confusing way.
Edit: Found the RFC for this: https://rust-lang.github.io/rfcs/1618-ergonomic-format-args.html
Edit 2: I found a Rust forum post which better addresses your question (https://internals.rust-lang.org/t/how-to-allow-arbitrary-expressions-in-format-strings/15812). Their reasoning is as follows:
Curly braces in format strings are escaped with curly braces: format!("{{foo}}") prints {foo}. If arbitrary expressions were supported, parsing this would become ambiguous.
It's ambiguous when type ascription is enabled: format!("{foo:X}") could mean either type ascription or that the UpperHex trait should be used.
The ? operator could be easily confused with Debug formatting: "{foo?}" and "{foo:?}" look very similar.
I read the below syntax from byteorder:
rdr.read_u16::<BigEndian>()
I can't find any documentation which explains the syntax instance.method::<SomeThing>()
This construct is called turbofish. If you search for this statement, you will discover its definition and its usage.
Although the first edition of The Rust Programming Language is outdated, I feel that this particular section is better than in the second book.
Quoting the second edition:
path::<...>, method::<...>
Specifies parameters to generic type, function, or method in an expression; often referred to as turbofish (e.g., "42".parse::<i32>())
You can use it in any kind of situation where the compiler is not able to deduce the type parameter, e.g.
fn main () {
let a = (0..255).sum();
let b = (0..255).sum::<u32>();
let c: u32 = (0..255).sum();
}
a does not work because it cannot deduce the variable type.
b does work because we specify the type parameter directly with the turbofish syntax.
c does work because we specify the type of c directly.
I tried to compile the following program:
use std::io;
fn main() {
io::stdout().write(b"Please enter your name: ");
io::stdout().flush();
}
Unfortunately, compiler resisted:
error: no method named `write` found for type `std::io::Stdout` in the current scope
--> hello.rs:4:18
|
4 | io::stdout().write(b"Please enter your name: ");
| ^^^^^
|
= help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
= help: candidate #1: `use std::io::Write`
I found that I needed to do use std::io::{self, Write};. What does use std::io; actually do then and how do (if possible) I pull all names defined in std::io? Also, would it be a bad style?
What does use std::io; actually do then?
It does what every use-statement does: makes the last part of the used path directly available (pulling it into the current namespace). That means that you can write io and the compiler knows that you mean std::io.
How do I pull all names defined in std::io?
With use std::io::*;. This is commonly referred to as glob-import.
Also, would it be a bad style?
Yes, it would. Usually you should avoid glob-imports. They can be handy for certain situations, but cause a lot of trouble on most cases. For example, there is also the trait std::fmt::Write... so importing everything from fmt and io would possibly result in name-clashes. Rust values explicitness over implicitness, so rather avoid glob-imports.
However, there is one type of module that is usually used with a glob-import: preludes. And in fact, there is even a std::io::prelude which reexports important symbols. See the documentation for more information.
This question already has answers here:
How to quiet a warning for a single statement in Rust?
(2 answers)
Closed 3 years ago.
I am getting some Clippy lints that look like this:
warning: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
--> src/helpers/mod.rs:29:32
|
29 | pub fn to_vec_sorted<U, F>(self, mapper: F) -> Vec<U>
| ^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention
I have no problem dealing with this lint, I just picked it because it doesn't show any proprietary code. Suppose I had a really good reason why I needed to name the function this way, and also that Clippy is integrated into my CI, so I need to have zero Clippy errors / warnings.
Is there a way to disable a Clippy lint for a particular line or code block, analogous to #SuppressWarnings("whatever") in Java? I feel like there must be, but I can't find any examples of doing this in the documentation.
The docs state you can allow or deny lints.
#[allow(clippy::wrong_self_convention)] pub fn to_vec_sorted<U, F>(self, mapper: F) -> Vec<U>
And ,if you want to disable all 1 of them:
#[allow(clippy::all)] pub fn to_vec_sorted<U, F>(self, mapper: F) -> Vec<U>
1: clippy:all doesn't actually allow all lints, rather everything contained by correctness, suspicious, style, complexity, cargo, and perf. This means no pedantic or nursery lints..
Using structs that reference each other is common in a single file, but when I separate the structs into two files, I get an error.
mod_1.rs
mod mod_2;
use mod_2::Haha;
pub struct Hehe {
obj: Haha,
}
fn main() {
Hehe(Haha);
}
mod_2.rs
mod mod_1;
use mod_1::Hehe;
pub struct Haha {
obj: Hehe,
}
fn main() {
Haha(Hehe);
}
This will produce an error. When compiling the mod_1.rs:
error: cannot declare a new module at this location
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
|
note: maybe move this module `mod_2` to its own directory via `mod_2/mod.rs`
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
note: ... or maybe `use` the module `mod_1` instead of possibly redeclaring it
--> mod_2.rs:1:5
|
1 | mod mod_1;
| ^^^^^
When compiling the mod_2.rs:
error: cannot declare a new module at this location
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
|
note: maybe move this module `mod_1` to its own directory via `mod_1/mod.rs`
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
--> mod_1.rs:1:5
|
1 | mod mod_2;
| ^^^^^
In mod_1.rs I use something from mod_2.rs and in mod_2.rs, I use mod_1.rs's thing, so I'd like to find a way to get rid of the cycle reference module problem.
Trying to get Rust to load files is a similar but different problem.
This is a common misunderstanding of Rust's module system. Basically, there are two steps:
You have to build a module-tree. This implies that there are not cycles in this module-tree and there is a clear parent-child relationship between nodes. This step is simply to tell Rust what files to load and has nothing to do with usage of certain symbols in different modules.
You can now reference each symbol in your module tree by its path (where each module and the final symbol name is separated by ::, for example std::io::read). In order to avoid writing the full path every time, you can use use declarations to refer to specific symbols by their simple name.
You can read a bit more on that in the Rust book chapter.
And again, to avoid confusion: in order to use a symbol from a module, you don't necessarily have to write mod my_module; in your module! For each non-root module of your project there is only one line in your entire project saying mod said_module; (the root module does not have such a line at all). Only once!
About your example: you first compiled mod_1.rs via rustc mod_1.rs. This means that mod_1 is the root module in your case. As explained above, the root module doesn't need to be declared via mod at all, but all other modules need to be declared exactly once. This means the mod mod_2; in mod_1.rs is completely correct, but the mod mod_1; in mod_2.rs is incorrect. The compiler even suggest the right thing to do:
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
You are already useing it, so you can just remove the line mod mod_1; and solve this error.
However, I think you are still thinking incorrectly about the module system. As mentioned above you first need to design a more or less fixed module tree which implies that you have one fixed root module. Whatever you pass to rustc is the root module and it doesn't make sense to use different modules as root module. In your project there should be one fixed root module. This could be mod_1 as explained above. But it's usually more idiomatic to call it lib for libraries and main for executables.
So again: first, draw your module tree on a piece of paper. Consider this fixed for the moment and then you can create the files and mod declarations appropriately.
Last thing: even when fixing the module system, your example won't work, because Haha and Hehe are types with infinite size. Fields of structs are directly put into the memory layout of the struct (without boxing them like in Java!). Thus you can't have cycles in struct definitions, except if you manually add a layer of indirection, like boxing the fields. Please read this excellent explanation on this issue.