I tried this code:
fn main(){
let a = (String::new(),0);
let ref _b = {a.0};
}
I expected the code to compile without warnings.
Instead, the unused_braces lint was triggered:
warning: unnecessary braces around assigned value
--> src/main.rs:4:18
|
4 | let ref _b = {a.0};
| ^^^^^ help: remove these braces
|
= note: `#[warn(unused_braces)]` on by default
This bug happens in 1.44.0-nightly (2020-04-01 76b11980ad416c3ad614),not in Rust beta nor stable.
Hello, thanks for the report!
Are the braces not unused? What you have here is
let ref _b = {
a.0
};
ie, assigning ref binding _b to a block which does nothing but return a.0 as its final expression, which is the same as just assigning directly without the braces (even with the ref).
This bug happens in 1.44.0-nightly (2020-04-01 76b1198),not in Rust beta nor stable.
The unused braces lint was added in b3d744c9f51b6bb42c7cebeb8f7fcefac8778d1e, which was after the current beta (4c587bbda04ab55aaf56feab11dfdfe387a85d7a).
The braces cause the .0 field to be moved,meaning that this doesn't compile:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=55ac4e94aa2b812a4dfafa4baedf86d4
fn main(){
let a = (String::new(),0);
let ref _b = {a.0};
// Can't print a partially moved value
println!("{:?}",a);
}
``
error[E0382]: borrow of moved value:a
--> src/main.rs:4:21
|
3 | let ref _b = {a.0};
| --- value moved here
4 | println!("{:?}",a);
| ^ value borrowed here after partial move
|
= note: move occurs becausea.0has typestd::string::String, which does not implement theCopy` trait
While this does:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d939ba3758c02849cc2cbe928990b73f
```rust
fn main(){
let a = (String::new(),0);
let ref _b = a.0;
println!("{:?}",a);
}
Oh, I see - very true! Thanks for clarifying.
For Copy types this can be devious as it means semantics change without a compilation error:
let a = 0;
let ref mut b = {a};
*b += 1;
assert_eq!(a, 0);
vs.
// `mut` qualifier is necessary, also not observed by the lint.
let mut a = 0;
let ref mut b = a;
*b += 1;
assert_eq!(a, 1);
This may also be triggered by a (IMO common) usage of the quote crate, but it only appears when running rustdoc:
[package]
name = "repro"
version = "0.1.0"
edition = "2018"
[dependencies]
quote = "=1.0.3"
use quote::quote;
pub fn repro() {
let many = [1, 2, 3];
let _together = quote! {
#(#many),*
};
}
% RUSTFLAGS=-Dwarnings cargo +nightly-2020-04-04 build
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
% RUSTFLAGS=-Dwarnings cargo +nightly-2020-04-04 doc
Documenting repro v0.1.0 (/private/tmp/repro)
warning: unnecessary braces around block return value
|
= note: `#[warn(unused_braces)]` on by default
Finished dev [unoptimized + debuginfo] target(s) in 0.82s
Ping @lcnr (author of the lint)
Are borrows and "pattern-matching contexts" the only ones where we need to silence the lint?
Do we lint after type-checking? We kind of need to, to take into account implicit borrows.
The issue with quote was actually mentioned in the original PR but somehow forgotten.
https://github.com/rust-lang/rust/pull/70081#issuecomment-600267175
@eddyb unused_braces currently only warns on top lvl exprs afaik. So I should probably stop linting for "pattern-matching contexts". I don't think that a lint based on syntax should know about types. i.e. changing types should not suddenly cause a warning because of unused braces (this is a personal preference though).
It's not about types, it's about implicit borrows, e.g. ({x.0}).clone(). But if you don't lint that at all then you should be good.
@shepmaster I fixed the issue concerning ref patterns for now, but don't yet have a good idea on how to fix the issue with quote.
Can you please open a new issue for this?
Can you please open a new issue for this?
Opened as #70814