rust-lang / rust-lang/rust-clippy

Incorrect suggestion for ptr_eq warning leads to vtable_address_comparisons error

Open
#6,524 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Suppose we start with the following code:

use std::rc::Rc;
pub trait Trait {}
pub fn eq(a: Rc<dyn Trait>, b: Rc<dyn Trait>) -> bool {
    Rc::ptr_eq(&a, &b)
}
error: comparing trait object pointers compares a non-unique vtable address
 --> src/lib.rs:4:5
  |
4 |     Rc::ptr_eq(&a, &b)
  |     ^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(clippy::vtable_address_comparisons)]` on by default
  = help: consider extracting and comparing data pointers only
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons

Okay, let’s do that:

pub fn eq(a: Rc<dyn Trait>, b: Rc<dyn Trait>) -> bool {
    &*a as *const dyn Trait as *const u8 == &*b as *const dyn Trait as *const u8
}
warning: use `std::ptr::eq` when comparing raw pointers
 --> src/lib.rs:4:5
  |
4 |     &*a as *const dyn Trait as *const u8 == &*b as *const dyn Trait as *const u8
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: try: `std::ptr::eq(&*a as *const dyn Trait, &*b as *const dyn Trait)`
  |
  = note: `#[warn(clippy::ptr_eq)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq

warning: 1 warning emitted

This suggestion is wrong. The cast to *const u8 is important, and removing it has led back to the first error:

pub fn eq(a: Rc<dyn Trait>, b: Rc<dyn Trait>) -> bool {
    std::ptr::eq(&*a as *const dyn Trait, &*b as *const dyn Trait)
}
error: comparing trait object pointers compares a non-unique vtable address
 --> src/lib.rs:4:5
  |
4 |     std::ptr::eq(&*a as *const dyn Trait, &*b as *const dyn Trait)
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[deny(clippy::vtable_address_comparisons)]` on by default
  = help: consider extracting and comparing data pointers only
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons
Meta
  • cargo clippy -V: clippy 0.0.212 (0b644e4 2020-12-26)
  • rustc -Vv:
    rustc 1.51.0-nightly (0b644e419 2020-12-26)
    binary: rustc
    commit-hash: 0b644e419681835bd0f5871c3bfbd648aa04f157
    commit-date: 2020-12-26
    host: x86_64-unknown-linux-gnu
    release: 1.51.0-nightly
    

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

Reproduce the reported Rc comparison with the vtable_address_comparisons and ptr_eq lints, then trace how the ptr_eq suggestion is generated. Done means the diagnostic no longer suggests comparing trait-object pointers without the required data-pointer cast, with a regression test covering the example.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.