about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-11 14:33:16 +0000
committerbors <bors@rust-lang.org>2023-12-11 14:33:16 +0000
commit8a3765582cb83733f8c344062729df0175409488 (patch)
tree8d12a60e5cd08152acc1800ccbb39652b8d28c35
parentff2c56344c764af598ad33027e9c7a48881808ef (diff)
parent5e1bfb538f195eeac02034c0779f42d34b0e869e (diff)
downloadrust-8a3765582cb83733f8c344062729df0175409488.tar.gz
rust-8a3765582cb83733f8c344062729df0175409488.zip
Auto merge of #117758 - Urgau:lint_pointer_trait_comparisons, r=davidtwco
Add lint against ambiguous wide pointer comparisons

This PR is the resolution of https://github.com/rust-lang/rust/issues/106447 decided in https://github.com/rust-lang/rust/issues/117717 by T-lang.

## `ambiguous_wide_pointer_comparisons`

*warn-by-default*

The `ambiguous_wide_pointer_comparisons` lint checks comparison of `*const/*mut ?Sized` as the operands.

### Example

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

let _ = a == b;
```

### Explanation

The comparison includes metadata which may not be expected.

-------

This PR also drops `clippy::vtable_address_comparisons` which is superseded by this one.

~~One thing: is the current naming right? `invalid` seems a bit too much.~~

Fixes https://github.com/rust-lang/rust/issues/117717
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs2
-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--compiler/rustc_span/src/symbol.rs2
-rw-r--r--library/alloc/tests/vec.rs2
-rw-r--r--library/core/src/cmp.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs6
-rw-r--r--library/core/src/ptr/mod.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs6
-rw-r--r--library/core/src/ptr/non_null.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs68
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr120
-rw-r--r--src/tools/clippy/tests/ui/vtable_address_comparisons.rs52
-rw-r--r--src/tools/clippy/tests/ui/vtable_address_comparisons.stderr68
-rw-r--r--src/tools/miri/tests/pass/pointers.rs1
-rw-r--r--src/tools/miri/tests/pass/rc.rs1
-rw-r--r--tests/ui/issues/issue-17336.rs3
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.rs138
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.stderr452
-rw-r--r--tests/ui/mir/mir_raw_fat_ptr.rs2
25 files changed, 933 insertions, 254 deletions
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 934e4b1786f..3607b7cd944 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -11,7 +11,7 @@
     thread_local
 )]
 #![no_core]
-#![allow(dead_code, internal_features)]
+#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
 
 #[lang = "sized"]
 pub trait Sized {}
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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f3c5138716d..0333b5f04c3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -520,6 +520,8 @@ symbols! {
         cmp,
         cmp_max,
         cmp_min,
+        cmp_partialeq_eq,
+        cmp_partialeq_ne,
         cmpxchg16b_target_feature,
         cmse_nonsecure_entry,
         coerce_unsized,
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 9e5910bf126..364dc920187 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1980,7 +1980,7 @@ fn vec_macro_repeating_null_raw_fat_pointer() {
 
     let vec = vec![null_raw_dyn; 1];
     dbg!(ptr_metadata(vec[0]));
-    assert!(vec[0] == null_raw_dyn);
+    assert!(std::ptr::eq(vec[0], null_raw_dyn));
 
     // Polyfill for https://github.com/rust-lang/rfcs/pull/2580
 
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 85246f4f3dc..d7c41ac5c06 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -230,6 +230,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
     /// by `==`.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_eq")]
     fn eq(&self, other: &Rhs) -> bool;
 
     /// This method tests for `!=`. The default implementation is almost always
@@ -237,6 +238,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_ne")]
     fn ne(&self, other: &Rhs) -> bool {
         !self.eq(other)
     }
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index bdf4ceeba4f..a444c30c756 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1772,6 +1772,7 @@ impl<T> *const [T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *const T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &*const T) -> bool {
         *self == *other
     }
@@ -1784,6 +1785,7 @@ impl<T: ?Sized> Eq for *const T {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Ord for *const T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn cmp(&self, other: &*const T) -> Ordering {
         if self < other {
             Less
@@ -1803,21 +1805,25 @@ impl<T: ?Sized> PartialOrd for *const T {
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn lt(&self, other: &*const T) -> bool {
         *self < *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn le(&self, other: &*const T) -> bool {
         *self <= *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn gt(&self, other: &*const T) -> bool {
         *self > *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn ge(&self, other: &*const T) -> bool {
         *self >= *other
     }
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 50cf29227ca..d6603681a0b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1897,6 +1897,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 #[inline(always)]
 #[must_use = "pointer comparison produces a value"]
 #[rustc_diagnostic_item = "ptr_eq"]
+#[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] // it's actually clear here
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index b07403bd53f..9e7b8ec64ac 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -2199,6 +2199,7 @@ impl<T> *mut [T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *mut T {
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &*mut T) -> bool {
         *self == *other
     }
@@ -2210,6 +2211,7 @@ impl<T: ?Sized> Eq for *mut T {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Ord for *mut T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn cmp(&self, other: &*mut T) -> Ordering {
         if self < other {
             Less
@@ -2229,21 +2231,25 @@ impl<T: ?Sized> PartialOrd for *mut T {
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn lt(&self, other: &*mut T) -> bool {
         *self < *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn le(&self, other: &*mut T) -> bool {
         *self <= *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn gt(&self, other: &*mut T) -> bool {
         *self > *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn ge(&self, other: &*mut T) -> bool {
         *self >= *other
     }
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 97fd7593ee1..77961506e13 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1791,6 +1791,7 @@ impl<T: ?Sized> Eq for NonNull<T> {}
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: ?Sized> PartialEq for NonNull<T> {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &Self) -> bool {
         self.as_ptr() == other.as_ptr()
     }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index b440e267efe..3627096ed91 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -684,7 +684,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::unit_types::UNIT_ARG_INFO,
     crate::unit_types::UNIT_CMP_INFO,
     crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
-    crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
     crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
     crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,
     crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 613f1ecc6fb..9f5897d2ca7 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -58,4 +58,5 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::undropped_manually_drops", "undropped_manually_drops"),
     ("clippy::unknown_clippy_lints", "unknown_lints"),
     ("clippy::unused_label", "unused_labels"),
+    ("clippy::vtable_address_comparisons", "ambiguous_wide_pointer_comparisons"),
 ];
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
index 41e13e13e56..cd2dacc9f09 100644
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
@@ -1,9 +1,8 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -29,31 +28,7 @@ declare_clippy_lint! {
     "comparison with an address of a function item"
 }
 
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparisons with an address of a trait vtable.
-    ///
-    /// ### Why is this bad?
-    /// Comparing trait objects pointers compares an vtable addresses which
-    /// are not guaranteed to be unique and could vary between different code generation units.
-    /// Furthermore vtables for different types could have the same address after being merged
-    /// together.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// let a: Rc<dyn Trait> = ...
-    /// let b: Rc<dyn Trait> = ...
-    /// if Rc::ptr_eq(&a, &b) {
-    ///     ...
-    /// }
-    /// ```
-    #[clippy::version = "1.44.0"]
-    pub VTABLE_ADDRESS_COMPARISONS,
-    correctness,
-    "comparison with an address of a trait vtable"
-}
-
-declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COMPARISONS]);
+declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
 
 impl LateLintPass<'_> for UnnamedAddress {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -64,51 +39,12 @@ impl LateLintPass<'_> for UnnamedAddress {
             )
         }
 
-        fn is_trait_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-            match cx.typeck_results().expr_ty_adjusted(expr).kind() {
-                ty::RawPtr(ty::TypeAndMut { ty, .. }) => ty.is_trait(),
-                _ => false,
-            }
-        }
-
         fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
             matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
         }
 
         if let ExprKind::Binary(binop, left, right) = expr.kind
             && is_comparison(binop.node)
-            && is_trait_ptr(cx, left)
-            && is_trait_ptr(cx, right)
-        {
-            span_lint_and_help(
-                cx,
-                VTABLE_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing trait object pointers compares a non-unique vtable address",
-                None,
-                "consider extracting and comparing data pointers only",
-            );
-        }
-
-        if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind
-            && let ExprKind::Path(ref func_qpath) = func.kind
-            && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
-            && cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id)
-            && let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0)
-            && ty_param.is_trait()
-        {
-            span_lint_and_help(
-                cx,
-                VTABLE_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing trait object pointers compares a non-unique vtable address",
-                None,
-                "consider extracting and comparing data pointers only",
-            );
-        }
-
-        if let ExprKind::Binary(binop, left, right) = expr.kind
-            && is_comparison(binop.node)
             && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
             && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
             && (is_fn_def(cx, left) || is_fn_def(cx, right))
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 4df9be2c21d..31f1ee6a86d 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -51,6 +51,7 @@
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 #![warn(clippy::almost_complete_range)]
 #![warn(clippy::disallowed_names)]
 #![warn(clippy::blocks_in_if_conditions)]
@@ -107,5 +108,6 @@
 #![warn(undropped_manually_drops)]
 #![warn(unknown_lints)]
 #![warn(unused_labels)]
+#![warn(ambiguous_wide_pointer_comparisons)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 940e60068e7..325bc356c15 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -51,6 +51,7 @@
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 #![warn(clippy::almost_complete_letter_range)]
 #![warn(clippy::blacklisted_name)]
 #![warn(clippy::block_in_if_condition_expr)]
@@ -107,5 +108,6 @@
 #![warn(clippy::undropped_manually_drops)]
 #![warn(clippy::unknown_clippy_lints)]
 #![warn(clippy::unused_label)]
+#![warn(clippy::vtable_address_comparisons)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 30824e154b8..a6164338c20 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,334 +8,340 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:99:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:100:9
+  --> $DIR/rename.rs:101:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:101:9
+  --> $DIR/rename.rs:102:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:102:9
+  --> $DIR/rename.rs:103:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:103:9
+  --> $DIR/rename.rs:104:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:104:9
+  --> $DIR/rename.rs:105:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:105:9
+  --> $DIR/rename.rs:106:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:106:9
+  --> $DIR/rename.rs:107:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> $DIR/rename.rs:107:9
+  --> $DIR/rename.rs:108:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:108:9
+  --> $DIR/rename.rs:109:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:109:9
+  --> $DIR/rename.rs:110:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 56 previous errors
+error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
+  --> $DIR/rename.rs:111:9
+   |
+LL | #![warn(clippy::vtable_address_comparisons)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
+
+error: aborting due to 57 previous errors
 
diff --git a/src/tools/clippy/tests/ui/vtable_address_comparisons.rs b/src/tools/clippy/tests/ui/vtable_address_comparisons.rs
deleted file mode 100644
index 75647c027e1..00000000000
--- a/src/tools/clippy/tests/ui/vtable_address_comparisons.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use std::fmt::Debug;
-use std::ptr;
-use std::rc::Rc;
-use std::sync::Arc;
-
-#[warn(clippy::vtable_address_comparisons)]
-#[allow(clippy::borrow_as_ptr)]
-
-fn main() {
-    let a: *const dyn Debug = &1 as &dyn Debug;
-    let b: *const dyn Debug = &1 as &dyn Debug;
-
-    // These should fail:
-    let _ = a == b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a != b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a < b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a <= b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a > b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a >= b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    ptr::eq(a, b);
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-
-    let a = &1 as &dyn Debug;
-    let b = &1 as &dyn Debug;
-    ptr::eq(a, b);
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-
-    // These should be fine:
-    let a = &1;
-    ptr::eq(a, a);
-
-    let a = Rc::new(1);
-    Rc::ptr_eq(&a, &a);
-
-    let a = Arc::new(1);
-    Arc::ptr_eq(&a, &a);
-
-    let a: Rc<dyn Debug> = Rc::new(1);
-    Rc::ptr_eq(&a, &a);
-
-    let a: Arc<dyn Debug> = Arc::new(1);
-    Arc::ptr_eq(&a, &a);
-
-    let a: &[u8] = b"";
-    ptr::eq(a, a);
-}
diff --git a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr b/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
deleted file mode 100644
index 83c82f3796e..00000000000
--- a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
+++ /dev/null
@@ -1,68 +0,0 @@
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:14:13
-   |
-LL |     let _ = a == b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-   = note: `-D clippy::vtable-address-comparisons` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::vtable_address_comparisons)]`
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:16:13
-   |
-LL |     let _ = a != b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:18:13
-   |
-LL |     let _ = a < b;
-   |             ^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:20:13
-   |
-LL |     let _ = a <= b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:22:13
-   |
-LL |     let _ = a > b;
-   |             ^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:24:13
-   |
-LL |     let _ = a >= b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:26:5
-   |
-LL |     ptr::eq(a, b);
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:31:5
-   |
-LL |     ptr::eq(a, b);
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: aborting due to 8 previous errors
-
diff --git a/src/tools/miri/tests/pass/pointers.rs b/src/tools/miri/tests/pass/pointers.rs
index 1525ded6151..c7b720dafa2 100644
--- a/src/tools/miri/tests/pass/pointers.rs
+++ b/src/tools/miri/tests/pass/pointers.rs
@@ -2,6 +2,7 @@
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 #![feature(ptr_metadata, const_raw_ptr_comparison)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::mem::{self, transmute};
 use std::ptr;
diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs
index 6375abcd232..6dd1b3aff9e 100644
--- a/src/tools/miri/tests/pass/rc.rs
+++ b/src/tools/miri/tests/pass/rc.rs
@@ -3,6 +3,7 @@
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(new_uninit)]
 #![feature(get_mut_unchecked)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::cell::{Cell, RefCell};
 use std::fmt::Debug;
diff --git a/tests/ui/issues/issue-17336.rs b/tests/ui/issues/issue-17336.rs
index 89ce59b11f2..97782ff9f0e 100644
--- a/tests/ui/issues/issue-17336.rs
+++ b/tests/ui/issues/issue-17336.rs
@@ -1,5 +1,8 @@
 // build-pass
+
 #![allow(unused_must_use)]
+#![allow(ambiguous_wide_pointer_comparisons)]
+
 #[allow(dead_code)]
 fn check(a: &str) {
     let x = a as *const str;
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
+
diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs
index 6aceefbe715..f4a9afd2308 100644
--- a/tests/ui/mir/mir_raw_fat_ptr.rs
+++ b/tests/ui/mir/mir_raw_fat_ptr.rs
@@ -1,7 +1,9 @@
 // run-pass
 // check raw fat pointer ops in mir
 // FIXME: please improve this when we get monomorphization support
+
 #![feature(raw_ref_op)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::mem;