about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2023-11-09 17:37:27 +0100
committerUrgau <urgau@numericable.fr>2023-12-06 09:03:48 +0100
commit5630540ac0536558c929cce0f1db5e9b8cfd0582 (patch)
tree3745992f9f62d679c4e881d8c13e0e04b536699d
parent26cbb10a5c6885d629cde3f8235800147b198bc0 (diff)
downloadrust-5630540ac0536558c929cce0f1db5e9b8cfd0582.tar.gz
rust-5630540ac0536558c929cce0f1db5e9b8cfd0582.zip
Add warn-by-default lint against ambiguous wide pointer comparisons
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/lints.rs70
-rw-r--r--compiler/rustc_lint/src/types.rs180
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.rs138
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.stderr452
5 files changed, 836 insertions, 8 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 2db610d640c..40e6b1b579f 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -1,3 +1,7 @@
+lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+    .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
+    .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+
 lint_array_into_iter =
     this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <{$target} as IntoIterator>::into_iter in Rust 2021
     .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 9fda53c2533..d0b895f7354 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1574,6 +1574,76 @@ pub enum InvalidNanComparisonsSuggestion {
     Spanless,
 }
 
+#[derive(LintDiagnostic)]
+pub enum AmbiguousWidePointerComparisons<'a> {
+    #[diag(lint_ambiguous_wide_pointer_comparisons)]
+    Spanful {
+        #[subdiagnostic]
+        addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
+        #[subdiagnostic]
+        addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
+    },
+    #[diag(lint_ambiguous_wide_pointer_comparisons)]
+    #[help(lint_addr_metadata_suggestion)]
+    #[help(lint_addr_suggestion)]
+    Spanless,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_addr_metadata_suggestion,
+    style = "verbose",
+    applicability = "machine-applicable"
+)]
+pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
+    pub ne: &'a str,
+    pub deref_left: &'a str,
+    pub deref_right: &'a str,
+    #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
+    pub left: Span,
+    #[suggestion_part(code = ", {deref_right}")]
+    pub middle: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
+    #[multipart_suggestion(
+        lint_addr_suggestion,
+        style = "verbose",
+        applicability = "machine-applicable"
+    )]
+    AddrEq {
+        ne: &'a str,
+        deref_left: &'a str,
+        deref_right: &'a str,
+        #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
+        left: Span,
+        #[suggestion_part(code = ", {deref_right}")]
+        middle: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
+    #[multipart_suggestion(
+        lint_addr_suggestion,
+        style = "verbose",
+        applicability = "machine-applicable"
+    )]
+    Cast {
+        deref_left: &'a str,
+        deref_right: &'a str,
+        #[suggestion_part(code = "{deref_left}")]
+        left_before: Option<Span>,
+        #[suggestion_part(code = " as *const ()")]
+        left: Span,
+        #[suggestion_part(code = "{deref_right}")]
+        right_before: Option<Span>,
+        #[suggestion_part(code = " as *const ()")]
+        right: Span,
+    },
+}
+
 pub struct ImproperCTypes<'a> {
     pub ty: Ty<'a>,
     pub desc: &'a str,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index bae63ae1716..810d691d16a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,12 +1,13 @@
 use crate::{
     fluent_generated as fluent,
     lints::{
-        AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
-        InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
-        OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
-        OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
-        OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
-        VariantSizeDifferencesDiag,
+        AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
+        AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
+        AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
+        InvalidNanComparisonsSuggestion, OnlyCastu8ToChar, OverflowingBinHex,
+        OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt,
+        OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange,
+        UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
     },
 };
 use crate::{LateContext, LateLintPass, LintContext};
@@ -17,10 +18,10 @@ use rustc_errors::DiagnosticMessage;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
-use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{
     self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
+use rustc_middle::ty::{GenericArgsRef, TypeAndMut};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
@@ -28,6 +29,7 @@ use rustc_span::{Span, Symbol};
 use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
+use rustc_type_ir::DynKind;
 
 use std::iter;
 use std::ops::ControlFlow;
@@ -136,6 +138,37 @@ declare_lint! {
     "detects invalid floating point NaN comparisons"
 }
 
+declare_lint! {
+    /// The `ambiguous_wide_pointer_comparisons` lint checks comparison
+    /// of `*const/*mut ?Sized` as the operands.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # struct A;
+    /// # struct B;
+    ///
+    /// # trait T {}
+    /// # impl T for A {}
+    /// # impl T for B {}
+    ///
+    /// let ab = (A, B);
+    /// let a = &ab.0 as *const dyn T;
+    /// let b = &ab.1 as *const dyn T;
+    ///
+    /// let _ = a == b;
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The comparison includes metadata which may not be expected.
+    AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+    Warn,
+    "detects ambiguous wide pointer comparisons"
+}
+
 #[derive(Copy, Clone)]
 pub struct TypeLimits {
     /// Id of the last visited negated expression
@@ -144,7 +177,12 @@ pub struct TypeLimits {
     negated_expr_span: Option<Span>,
 }
 
-impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS, INVALID_NAN_COMPARISONS]);
+impl_lint_pass!(TypeLimits => [
+    UNUSED_COMPARISONS,
+    OVERFLOWING_LITERALS,
+    INVALID_NAN_COMPARISONS,
+    AMBIGUOUS_WIDE_POINTER_COMPARISONS
+]);
 
 impl TypeLimits {
     pub fn new() -> TypeLimits {
@@ -620,6 +658,106 @@ fn lint_nan<'tcx>(
     cx.emit_spanned_lint(INVALID_NAN_COMPARISONS, e.span, lint);
 }
 
+fn lint_wide_pointer<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx hir::Expr<'tcx>,
+    binop: hir::BinOpKind,
+    l: &'tcx hir::Expr<'tcx>,
+    r: &'tcx hir::Expr<'tcx>,
+) {
+    let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(usize, bool)> {
+        let mut refs = 0;
+        // here we remove any "implicit" references and count the number
+        // of them to correctly suggest the right number of deref
+        while let ty::Ref(_, inner_ty, _) = ty.kind() {
+            ty = *inner_ty;
+            refs += 1;
+        }
+        match ty.kind() {
+            ty::RawPtr(TypeAndMut { mutbl: _, ty }) => (!ty.is_sized(cx.tcx, cx.param_env))
+                .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, DynKind::Dyn)))),
+            _ => None,
+        }
+    };
+
+    // PartialEq::{eq,ne} takes references, remove any explicit references
+    let l = l.peel_borrows();
+    let r = r.peel_borrows();
+
+    let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else {
+        return;
+    };
+    let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else {
+        return;
+    };
+
+    let Some((l_ty_refs, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else {
+        return;
+    };
+    let Some((r_ty_refs, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else {
+        return;
+    };
+
+    let (Some(l_span), Some(r_span)) =
+        (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
+    else {
+        return cx.emit_spanned_lint(
+            AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+            e.span,
+            AmbiguousWidePointerComparisons::Spanless,
+        );
+    };
+
+    let ne = if binop == hir::BinOpKind::Ne { "!" } else { "" };
+    let is_eq_ne = matches!(binop, hir::BinOpKind::Eq | hir::BinOpKind::Ne);
+    let is_dyn_comparison = l_inner_ty_is_dyn && r_inner_ty_is_dyn;
+
+    let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
+    let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
+    let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi());
+
+    let deref_left = &*"*".repeat(l_ty_refs);
+    let deref_right = &*"*".repeat(r_ty_refs);
+
+    cx.emit_spanned_lint(
+        AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+        e.span,
+        AmbiguousWidePointerComparisons::Spanful {
+            addr_metadata_suggestion: (is_eq_ne && !is_dyn_comparison).then(|| {
+                AmbiguousWidePointerComparisonsAddrMetadataSuggestion {
+                    ne,
+                    deref_left,
+                    deref_right,
+                    left,
+                    middle,
+                    right,
+                }
+            }),
+            addr_suggestion: if is_eq_ne {
+                AmbiguousWidePointerComparisonsAddrSuggestion::AddrEq {
+                    ne,
+                    deref_left,
+                    deref_right,
+                    left,
+                    middle,
+                    right,
+                }
+            } else {
+                AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
+                    deref_left,
+                    deref_right,
+                    // those two Options are required for correctness as having
+                    // an empty span and an empty suggestion is not permitted
+                    left_before: (l_ty_refs != 0).then_some(left),
+                    right_before: (r_ty_refs != 0).then(|| r_span.shrink_to_lo()),
+                    left: l_span.shrink_to_hi(),
+                    right,
+                }
+            },
+        },
+    );
+}
+
 impl<'tcx> LateLintPass<'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
@@ -636,10 +774,26 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                         cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
                     } else {
                         lint_nan(cx, e, binop, l, r);
+                        lint_wide_pointer(cx, e, binop.node, l, r);
                     }
                 }
             }
             hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit),
+            hir::ExprKind::Call(path, [l, r])
+                if let ExprKind::Path(ref qpath) = path.kind
+                    && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                    && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+                    && let Some(binop) = partialeq_binop(diag_item) =>
+            {
+                lint_wide_pointer(cx, e, binop, l, r);
+            }
+            hir::ExprKind::MethodCall(_, l, [r], _)
+                if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+                    && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+                    && let Some(binop) = partialeq_binop(diag_item) =>
+            {
+                lint_wide_pointer(cx, e, binop, l, r);
+            }
             _ => {}
         };
 
@@ -722,6 +876,16 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     | hir::BinOpKind::Gt
             )
         }
+
+        fn partialeq_binop(diag_item: Symbol) -> Option<hir::BinOpKind> {
+            if diag_item == sym::cmp_partialeq_eq {
+                Some(hir::BinOpKind::Eq)
+            } else if diag_item == sym::cmp_partialeq_ne {
+                Some(hir::BinOpKind::Ne)
+            } else {
+                None
+            }
+        }
     }
 }
 
diff --git a/tests/ui/lint/wide_pointer_comparisons.rs b/tests/ui/lint/wide_pointer_comparisons.rs
new file mode 100644
index 00000000000..8334575cf52
--- /dev/null
+++ b/tests/ui/lint/wide_pointer_comparisons.rs
@@ -0,0 +1,138 @@
+// check-pass
+
+use std::rc::Rc;
+use std::sync::Arc;
+use std::cmp::PartialEq;
+
+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
+
+    {
+        // &*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 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: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);
+}
diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr
new file mode 100644
index 00000000000..926b8775902
--- /dev/null
+++ b/tests/ui/lint/wide_pointer_comparisons.stderr
@@ -0,0 +1,452 @@
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:19:13
+   |
+LL |     let _ = a == b;
+   |             ^^^^^^
+   |
+   = note: `#[warn(ambiguous_wide_pointer_comparisons)]` on by default
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ++++++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:21:13
+   |
+LL |     let _ = a != b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             +++++++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:23:13
+   |
+LL |     let _ = a < b;
+   |             ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () < b as *const ();
+   |               ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:25:13
+   |
+LL |     let _ = a <= b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () <= b as *const ();
+   |               ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:27:13
+   |
+LL |     let _ = a > b;
+   |             ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () > b as *const ();
+   |               ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:29:13
+   |
+LL |     let _ = a >= b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () >= b as *const ();
+   |               ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:32:13
+   |
+LL |     let _ = PartialEq::eq(&a, &b);
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ~~~~~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:34:13
+   |
+LL |     let _ = PartialEq::ne(&a, &b);
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             ~~~~~~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:36:13
+   |
+LL |     let _ = a.eq(&b);
+   |             ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ++++++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:38:13
+   |
+LL |     let _ = a.ne(&b);
+   |             ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             +++++++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:46:17
+   |
+LL |         let _ = a == b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 +++++++++++++++++++ ~~~ +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:48:17
+   |
+LL |         let _ = a != b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ++++++++++++++++++++ ~~~ +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:50:17
+   |
+LL |         let _ = a < b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () < *b as *const ();
+   |                 +  ++++++++++++   +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:52:17
+   |
+LL |         let _ = a <= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () <= *b as *const ();
+   |                 +  ++++++++++++    +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:54:17
+   |
+LL |         let _ = a > b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () > *b as *const ();
+   |                 +  ++++++++++++   +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:56:17
+   |
+LL |         let _ = a >= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () >= *b as *const ();
+   |                 +  ++++++++++++    +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:59:17
+   |
+LL |         let _ = PartialEq::eq(a, b);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:61:17
+   |
+LL |         let _ = PartialEq::ne(a, b);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:63:17
+   |
+LL |         let _ = PartialEq::eq(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:65:17
+   |
+LL |         let _ = PartialEq::ne(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:67:17
+   |
+LL |         let _ = a.eq(b);
+   |                 ^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 +++++++++++++++++++ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:69:17
+   |
+LL |         let _ = a.ne(b);
+   |                 ^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ++++++++++++++++++++ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:74:13
+   |
+LL |     let _ = s == s;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(s, s);
+   |             ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |     let _ = std::ptr::eq(s, s);
+   |             +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:78:13
+   |
+LL |     let _ = s == s;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(s, s);
+   |             ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |     let _ = std::ptr::eq(s, s);
+   |             +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:82:17
+   |
+LL |         let _ = a == b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:84:17
+   |
+LL |         let _ = a != b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 +++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:86:17
+   |
+LL |         let _ = a < b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () < b as *const ();
+   |                   ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:88:17
+   |
+LL |         let _ = a <= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () <= b as *const ();
+   |                   ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:90:17
+   |
+LL |         let _ = a > b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () > b as *const ();
+   |                   ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:92:17
+   |
+LL |         let _ = a >= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () >= b as *const ();
+   |                   ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:95:17
+   |
+LL |         let _ = PartialEq::eq(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ~~~~~~~~~~~~~~~~~~ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 ~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:97:17
+   |
+LL |         let _ = PartialEq::ne(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:99:17
+   |
+LL |         let _ = a.eq(&b);
+   |                 ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ++++++++++++++++++ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 +++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:101:17
+   |
+LL |         let _ = a.ne(&b);
+   |                 ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 +++++++++++++++++++ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:106:9
+   |
+LL |         &*a == &*b
+   |         ^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         std::ptr::addr_eq(*a, *b)
+   |         ~~~~~~~~~~~~~~~~~~  ~   +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         std::ptr::eq(*a, *b)
+   |         ~~~~~~~~~~~~~  ~   +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:112:39
+   |
+LL |             ($a:ident, $b:ident) => { $a == $b }
+   |                                       ^^^^^^^^
+...
+LL |         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 `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |             ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) }
+   |                                       ++++++++++++++++++  ~   +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:122:37
+   |
+LL |             ($a:expr, $b:expr) => { $a == $b }
+   |                                     ^^
+...
+LL |         cmp!(&a, &b);
+   |         ------------ in this macro invocation
+   |
+   = help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   = help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 37 warnings emitted
+