Skip to content

unused_must_use triggers inside macro where suggestion does not make sense #143025

@matthiaskrgr

Description

@matthiaskrgr

Using the following flags

--force-warn unused_must_use

this code:

//@ check-pass

use std::rc::Rc;
use std::sync::Arc;
use std::cmp::PartialEq;
use std::ptr::NonNull;

struct A;
struct B;

trait T {}
impl T for A {}
impl T for B {}

fn main() {
    let ab = (A, B);
    let a = &ab.0 as *const dyn T;
    let b = &ab.1 as *const dyn T;

    let _ = a == b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a != b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a < b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a <= b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a > b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a >= b;
    //~^ WARN ambiguous wide pointer comparison

    let _ = PartialEq::eq(&a, &b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = PartialEq::ne(&a, &b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.eq(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.ne(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.cmp(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.partial_cmp(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.le(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.lt(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.ge(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.gt(&b);
    //~^ WARN ambiguous wide pointer comparison

    {
        let a = NonNull::<dyn T>::new(a as *mut _).unwrap();
        let b = NonNull::<dyn T>::new(b as *mut _).unwrap();
        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = &a == &b;
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        // &*const ?Sized
        let a = &a;
        let b = &b;

        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a != b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a < b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a <= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a > b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison

        let _ = PartialEq::eq(a, b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(a, b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::eq(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.eq(b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ne(b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.cmp(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.partial_cmp(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.le(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.lt(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ge(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.gt(&b);
        //~^ WARN ambiguous wide pointer comparison
    }

    let s = "" as *const str;
    let _ = s == s;
    //~^ WARN ambiguous wide pointer comparison

    let s = &[8, 7][..] as *const [i32];
    let _ = s == s;
    //~^ WARN ambiguous wide pointer comparison

    fn cmp<T: ?Sized>(a: *mut T, b: *mut T) -> bool {
        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a != b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a < b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a <= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a > b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison

        let _ = PartialEq::eq(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.eq(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ne(&b);
        //~^ WARN ambiguous wide pointer comparison

        let a = &a;
        let b = &b;
        &*a == &*b
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        macro_rules! cmp {
            ($a:tt, $b:tt) => { $a == $b }
        }

        // FIXME: This lint uses some custom span combination logic.
        // Rewrite it to adapt to the new metavariable span rules.
        cmp!(a, b);
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        macro_rules! cmp {
            ($a:ident, $b:ident) => { $a == $b }
            //~^ WARN ambiguous wide pointer comparison
        }

        cmp!(a, b);
    }

    {
        // this produce weird diagnostics
        macro_rules! cmp {
            ($a:expr, $b:expr) => { $a == $b }
            //~^ WARN ambiguous wide pointer comparison
        }

        cmp!(&a, &b);
    }

    let _ = std::ptr::eq(a, b);
    let _ = std::ptr::addr_eq(a, b);
    let _ = a as *const () == b as *const ();

    let a: Rc<dyn std::fmt::Debug> = Rc::new(1);
    Rc::ptr_eq(&a, &a);

    let a: Arc<dyn std::fmt::Debug> = Arc::new(1);
    Arc::ptr_eq(&a, &a);
}

caused the following diagnostics:

    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on shared package cache
    Checking _wide_pointer_comparisons v0.1.0 (/tmp/icemaker_global_tempdir.hTWDZB3NcvpG/icemaker_clippyfix_tempdir.ZkFeOthGJg8C/_wide_pointer_comparisons)
warning: unused comparison that must be used
   --> src/main.rs:153:14
    |
153 |         cmp!(a, b);
    |              ^^^^ the comparison produces a value
    |
    = note: requested on the command line with `--force-warn unused-must-use`
help: use `let _ = ...` to ignore the resulting value
    |
153 |         cmp!(let _ = a, b);
    |              +++++++

warning: unused comparison that must be used
   --> src/main.rs:159:39
    |
159 |             ($a:ident, $b:ident) => { $a == $b }
    |                                       ^^^^^^^^ the comparison produces a value
...
163 |         cmp!(a, b);
    |         ---------- in this macro invocation
    |
    = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use `let _ = ...` to ignore the resulting value
    |
159 |             ($a:ident, $b:ident) => { let _ = $a == $b }
    |                                       +++++++

warning: unused comparison that must be used
   --> src/main.rs:169:37
    |
169 |             ($a:expr, $b:expr) => { $a == $b }
    |                                     ^^^^^^^^ the comparison produces a value
...
173 |         cmp!(&a, &b);
    |         ------------ in this macro invocation
    |
    = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
help: use `let _ = ...` to ignore the resulting value
    |
169 |             ($a:expr, $b:expr) => { let _ = $a == $b }
    |                                     +++++++

warning: unused return value of `std::sync::Arc::<T, A>::ptr_eq` that must be used
   --> src/main.rs:184:5
    |
184 |     Arc::ptr_eq(&a, &a);
    |     ^^^^^^^^^^^^^^^^^^^
    |
help: use `let _ = ...` to ignore the resulting value
    |
184 |     let _ = Arc::ptr_eq(&a, &a);
    |     +++++++

warning: `_wide_pointer_comparisons` (bin "_wide_pointer_comparisons") generated 4 warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.49s

However after applying these diagnostics, the resulting code:

//@ check-pass

use std::rc::Rc;
use std::sync::Arc;
use std::cmp::PartialEq;
use std::ptr::NonNull;

struct A;
struct B;

trait T {}
impl T for A {}
impl T for B {}

fn main() {
    let ab = (A, B);
    let a = &ab.0 as *const dyn T;
    let b = &ab.1 as *const dyn T;

    let _ = a == b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a != b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a < b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a <= b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a > b;
    //~^ WARN ambiguous wide pointer comparison
    let _ = a >= b;
    //~^ WARN ambiguous wide pointer comparison

    let _ = PartialEq::eq(&a, &b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = PartialEq::ne(&a, &b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.eq(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.ne(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.cmp(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.partial_cmp(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.le(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.lt(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.ge(&b);
    //~^ WARN ambiguous wide pointer comparison
    let _ = a.gt(&b);
    //~^ WARN ambiguous wide pointer comparison

    {
        let a = NonNull::<dyn T>::new(a as *mut _).unwrap();
        let b = NonNull::<dyn T>::new(b as *mut _).unwrap();
        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = &a == &b;
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        // &*const ?Sized
        let a = &a;
        let b = &b;

        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a != b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a < b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a <= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a > b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison

        let _ = PartialEq::eq(a, b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(a, b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::eq(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.eq(b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ne(b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.cmp(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.partial_cmp(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.le(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.lt(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ge(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.gt(&b);
        //~^ WARN ambiguous wide pointer comparison
    }

    let s = "" as *const str;
    let _ = s == s;
    //~^ WARN ambiguous wide pointer comparison

    let s = &[8, 7][..] as *const [i32];
    let _ = s == s;
    //~^ WARN ambiguous wide pointer comparison

    fn cmp<T: ?Sized>(a: *mut T, b: *mut T) -> bool {
        let _ = a == b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a != b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a < b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a <= b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a > b;
        //~^ WARN ambiguous wide pointer comparison
        let _ = a >= b;
        //~^ WARN ambiguous wide pointer comparison

        let _ = PartialEq::eq(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = PartialEq::ne(&a, &b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.eq(&b);
        //~^ WARN ambiguous wide pointer comparison
        let _ = a.ne(&b);
        //~^ WARN ambiguous wide pointer comparison

        let a = &a;
        let b = &b;
        &*a == &*b
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        macro_rules! cmp {
            ($a:tt, $b:tt) => { $a == $b }
        }

        // FIXME: This lint uses some custom span combination logic.
        // Rewrite it to adapt to the new metavariable span rules.
        cmp!(let _ = a, b);
        //~^ WARN ambiguous wide pointer comparison
    }

    {
        macro_rules! cmp {
            ($a:ident, $b:ident) => { let _ = $a == $b }
            //~^ WARN ambiguous wide pointer comparison
        }

        cmp!(a, b);
    }

    {
        // this produce weird diagnostics
        macro_rules! cmp {
            ($a:expr, $b:expr) => { let _ = $a == $b }
            //~^ WARN ambiguous wide pointer comparison
        }

        cmp!(&a, &b);
    }

    let _ = std::ptr::eq(a, b);
    let _ = std::ptr::addr_eq(a, b);
    let _ = a as *const () == b as *const ();

    let a: Rc<dyn std::fmt::Debug> = Rc::new(1);
    Rc::ptr_eq(&a, &a);

    let a: Arc<dyn std::fmt::Debug> = Arc::new(1);
    let _ = Arc::ptr_eq(&a, &a);
}

no longer compiled:

    Checking _wide_pointer_comparisons v0.1.0 (/tmp/icemaker_global_tempdir.hTWDZB3NcvpG/icemaker_clippyfix_tempdir.ZkFeOthGJg8C/_wide_pointer_comparisons)
error: no rules expected reserved identifier `_`
   --> src/main.rs:153:18
    |
147 |         macro_rules! cmp {
    |         ---------------- when calling this macro
...
153 |         cmp!(let _ = a, b);
    |                  ^ no rules expected this token in macro call
    |
note: while trying to match `,`
   --> src/main.rs:148:19
    |
148 |             ($a:tt, $b:tt) => { $a == $b }
    |                   ^

error: macro expansion ends with an incomplete expression: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator
   --> src/main.rs:159:55
    |
159 |             ($a:ident, $b:ident) => { let _ = $a == $b }
    |                                                       ^ expected one of 8 possible tokens

error: macro expansion ends with an incomplete expression: expected one of `.`, `;`, `?`, `else`, or an operator
   --> src/main.rs:169:53
    |
169 |             ($a:expr, $b:expr) => { let _ = $a == $b }
    |                                                     ^ expected one of `.`, `;`, `?`, `else`, or an operator

error: could not compile `_wide_pointer_comparisons` (bin "_wide_pointer_comparisons" test) due to 3 previous errors
warning: build failed, waiting for other jobs to finish...
error: could not compile `_wide_pointer_comparisons` (bin "_wide_pointer_comparisons") due to 3 previous errors

Version:

rustc 1.90.0-nightly (8cf5fad73 2025-06-25)
binary: rustc
commit-hash: 8cf5fad73d4e8f41863ecc3bcfa114eabc951faa
commit-date: 2025-06-25
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-bugCategory: This is a bug.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions