rust-lang / rust-lang/rust-clippy

borrow_as_ptr false positive on sequence of pointer casts

Open
#8,286 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-false-positive
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Summary

Clippy prefers that I make the following change:

- unsafe { &*(&**thing as *const T as *const U) }
+ unsafe { &*(ptr::addr_of!(**thing) as *const U) }

I consider this a false positive because the suggested code is only more brittle compared to the original code:

  • In the original code, it's clear without even showing the definition of thing that **thing is of type T, as otherwise we could not cast from &T to *const T. It's unlikely that you could have written too few or too many * and still get something that compiles, so this is "type safe".

  • In the suggested code, addr_of! will take whatever almost arbitrary place expression you give it and take its address, that then gets casted to *const U. If you got too many or too few * in there, this code will silently or not-so-silently or not-so-harmlessly do the wrong thing. If you got the right number of * today but tomorrow thing changes type, that code becomes almost certainly wrong without any compile error.

This use case is minimized from real-world code in https://github.com/dtolnay/cargo-tally/blob/1.0.2/src/arena.rs#L81.

Lint Name

borrow_as_ptr

Reproducer
#![deny(clippy::pedantic)]
#![allow(clippy::cast_ptr_alignment, clippy::ptr_as_ptr)]

#[derive(Debug)]
#[repr(C)]
struct Thing { _i: i32 }

fn main() {
    let thing = &Box::new(1i32);

    let reference = unsafe { &*(&**thing as *const i32 as *const Thing) };
    println!("{:?}", reference);
}
$ cargo clippy

error: borrow as raw pointer
  --> src/main.rs:11:33
   |
11 |     let reference = unsafe { &*(&**thing as *const i32 as *const Thing) };
   |                                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(**thing)`
   |
note: the lint level is defined here
  --> src/main.rs:1:9
   |
1  | #![deny(clippy::pedantic)]
   |         ^^^^^^^^^^^^^^^^
   = note: `#[deny(clippy::borrow_as_ptr)]` implied by `#[deny(clippy::pedantic)]`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr
Version
rustc 1.60.0-nightly (ad46af247 2022-01-14)
binary: rustc
commit-hash: ad46af24713115e7b9b258346e66b9b2d14eacfc
commit-date: 2022-01-14
host: x86_64-unknown-linux-gnu
release: 1.60.0-nightly
LLVM version: 13.0.0
Additional Labels

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the borrow_as_ptr lint and the Rust reproducer in the issue, then run cargo clippy to confirm the current suggestion. Trace how the sequence of pointer casts is recognized and determine the expected behavior for this case; done means the false positive is handled without breaking the lint's existing checks.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.