Rust: Unused braces lint triggers on partial move into ref pattern.

Created on 2 Apr 2020  路  11Comments  路  Source: rust-lang/rust

I tried this code:

fn main(){
    let a = (String::new(),0);
    let ref _b = {a.0};
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=4b8d234e04e2d77ab45ecf3c41d59d58

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

Meta

This bug happens in 1.44.0-nightly (2020-04-01 76b11980ad416c3ad614),not in Rust beta nor stable.

A-lint C-bug T-compiler

All 11 comments

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

Was this page helpful?
0 / 5 - 0 ratings