Lint for reading entire struct instead of field

When writing unsafe code you may accidentally write this:

#[derive(Copy,Clone)]
struct Foo {
    field: u32,
    field2: u16,
}

fn foo(ptr: *const Foo) -> u32 {
    unsafe { *ptr }.field
}

The foo function unfortunately reads the entire struct Foo and then reads field from the copy of Foo. The user probably meant to write unsafe { (*ptr).field }. Is there a clippy lint for this scenario?

It doesn't appear so.

 #![warn(
     clippy::all,
     clippy::restriction,
     clippy::pedantic,
     clippy::nursery,
     clippy::cargo,
 )]

#[derive(Copy, Clone)]
struct Foo {
    foo: u32,
}

fn main() {
    let f = Foo { foo: 42 };
    let f = get_f(&raw const f);
    println!("Hello, world {f}");
}

const fn get_f(f: *const Foo) -> u32 {
    unsafe { *f }.foo
}
~/clippy_test> cargo clippy 
warning: `clippy::restriction` is not meant to be enabled as a group
 --> src/main.rs:3:6
  |
3 |      clippy::restriction,
  |      ^^^^^^^^^^^^^^^^^^^
  |
  = help: enable the restriction lints you need individually
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
note: the lint level is defined here
 --> src/main.rs:2:6
  |
2 |      clippy::all,
  |      ^^^^^^^^^^^
  = note: `#[warn(clippy::blanket_clippy_restriction_lints)]` implied by `#[warn(clippy::all)]`

warning: missing documentation for the crate
  --> src/main.rs:1:2
   |
1  | /  #![warn(
2  | |      clippy::all,
3  | |      clippy::restriction,
4  | |      clippy::pedantic,
...  |
21 | |     unsafe { *f }.foo
22 | | }
   | |_^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
note: the lint level is defined here
  --> src/main.rs:3:6
   |
3  |      clippy::restriction,
   |      ^^^^^^^^^^^^^^^^^^^
   = note: `#[warn(clippy::missing_docs_in_private_items)]` implied by `#[warn(clippy::restriction)]`

warning: package `clippy_test` is missing `package.description` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata
note: the lint level is defined here
 --> src/main.rs:6:6
  |
6 |      clippy::cargo,
  |      ^^^^^^^^^^^^^
  = note: `#[warn(clippy::cargo_common_metadata)]` implied by `#[warn(clippy::cargo)]`

warning: package `clippy_test` is missing `either package.license or package.license_file` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata

warning: package `clippy_test` is missing `package.repository` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata

warning: package `clippy_test` is missing `package.readme` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata

warning: package `clippy_test` is missing `package.keywords` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata

warning: package `clippy_test` is missing `package.categories` metadata
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata

warning: missing documentation for a struct
  --> src/main.rs:10:1
   |
10 | / struct Foo {
11 | |     foo: u32,
12 | | }
   | |_^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items

warning: missing documentation for a struct field
  --> src/main.rs:11:5
   |
11 |     foo: u32,
   |     ^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items

warning: this ident consists of a single char
  --> src/main.rs:15:9
   |
15 |     let f = Foo { foo: 42 };
   |         ^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars
   = note: `#[warn(clippy::min_ident_chars)]` implied by `#[warn(clippy::restriction)]`

warning: `f` is shadowed
  --> src/main.rs:16:9
   |
16 |     let f = get_f(&raw const f);
   |         ^
   |
note: previous binding is here
  --> src/main.rs:15:9
   |
15 |     let f = Foo { foo: 42 };
   |         ^
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
   = note: `#[warn(clippy::shadow_reuse)]` implied by `#[warn(clippy::restriction)]`

warning: this ident consists of a single char
  --> src/main.rs:16:9
   |
16 |     let f = get_f(&raw const f);
   |         ^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars

warning: use of `println!`
  --> src/main.rs:17:5
   |
17 |     println!("Hello, world {f}");
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout
   = note: `#[warn(clippy::print_stdout)]` implied by `#[warn(clippy::restriction)]`

warning: missing documentation for a function
  --> src/main.rs:20:1
   |
20 | / const fn get_f(f: *const Foo) -> u32 {
21 | |     unsafe { *f }.foo
22 | | }
   | |_^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items

warning: missing `return` statement
  --> src/main.rs:21:5
   |
21 |     unsafe { *f }.foo
   |     ^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
   = note: `#[warn(clippy::implicit_return)]` implied by `#[warn(clippy::restriction)]`
help: add `return` as shown
   |
21 |     return unsafe { *f }.foo
   |     ++++++

warning: this ident consists of a single char
  --> src/main.rs:20:16
   |
20 | const fn get_f(f: *const Foo) -> u32 {
   |                ^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars

warning: unsafe block missing a safety comment
  --> src/main.rs:21:5
   |
21 |     unsafe { *f }.foo
   |     ^^^^^^^^^^^^^
   |
   = help: consider adding a safety comment on the preceding line
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks
   = note: `#[warn(clippy::undocumented_unsafe_blocks)]` implied by `#[warn(clippy::restriction)]`

warning: this function is only used once
  --> src/main.rs:20:1
   |
20 | / const fn get_f(f: *const Foo) -> u32 {
21 | |     unsafe { *f }.foo
22 | | }
   | |_^
   |
note: used here
  --> src/main.rs:16:13
   |
16 |     let f = get_f(&raw const f);
   |             ^^^^^
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn
   = note: `#[warn(clippy::single_call_fn)]` implied by `#[warn(clippy::restriction)]`

warning: `clippy_test` (bin "clippy_test") generated 19 warnings (run `cargo clippy --fix --bin "clippy_test"` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
~/clippy_test>

However, both cases compile to the same assembly code:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.