rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.07k stars 1.49k forks source link

needless_update false positive when struct definition or struct expression uses `cfg` #13076

Open dtolnay opened 1 week ago

dtolnay commented 1 week ago

Summary

There are cases where a struct expression using functional update syntax is the best way to express what I want, but some of the fields in the struct are conditionally compiled, and under some feature combinations it can be possible that the .. part of the struct expression contains no fields.

Example: some of the method implementations in https://github.com/dtolnay/syn/blob/2.0.70/src/fixup.rs.

Lint Name

needless_update

Reproducer

Struct definition uses conditional compilation:

struct Struct {
    #[cfg(feature = "a")]
    a: bool,

    #[cfg(feature = "b")]
    b: bool,
}

impl Struct {
    #[cfg(feature = "a")]
    fn a(self) -> Self {
        Struct { a: true, ..self }
    }
}
$ cargo clippy --features a
warning: struct update has no effect, all the fields in the struct have already been specified
  --> src/main.rs:12:29
   |
12 |         Struct { a: true, ..self }
   |                             ^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
   = note: `#[warn(clippy::needless_update)]` on by default

Struct expression uses conditional compilation:

struct Struct {
    a: bool,
}

impl Struct {
    fn a(self) -> Self {
        Struct {
            #[cfg(feature = "a")]
            a: true,
            ..self
        }
    }
}
$ cargo clippy --features a
warning: struct update has no effect, all the fields in the struct have already been specified
  --> src/main.rs:10:15
   |
10 |             ..self
   |               ^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
   = note: `#[warn(clippy::needless_update)]` on by default

Version

rustc 1.81.0-nightly (20ae37c18 2024-07-07)
binary: rustc
commit-hash: 20ae37c18df95f9246c019b04957d23b4164bf7a
commit-date: 2024-07-07
host: x86_64-unknown-linux-gnu
release: 1.81.0-nightly
LLVM version: 18.1.7

Additional Labels

No response

dtolnay commented 1 week ago

One might expect that this can be worked around by using another cfg to only include the .. when it is nonempty:

but that is not valid Rust syntax.