Skip to content

Commit

Permalink
Auto merge of rust-lang#123207 - Urgau:improve_ambi_non_null, r=Nadri…
Browse files Browse the repository at this point in the history
…eril

Add support for `NonNull`s in the `ambiguous_wide_ptr_comparisions` lint

This PR add support for `NonNull` pointers in the `ambiguous_wide_ptr_comparisions` lint.

Fixes rust-lang#121264
r? `@Nadrieril` (since you just reviewed rust-lang#121268, feel free to reassign)
  • Loading branch information
bors committed Mar 30, 2024
2 parents 1852728 + 16d11c5 commit ef49365
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 65 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/tagged_ptr/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ where
T: Tag,
{
#[inline]
#[allow(ambiguous_wide_pointer_comparisons)]
fn eq(&self, other: &Self) -> bool {
self.packed == other.packed
}
Expand Down
18 changes: 12 additions & 6 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,11 +1632,13 @@ pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
pub ne: &'a str,
pub deref_left: &'a str,
pub deref_right: &'a str,
pub l_modifiers: &'a str,
pub r_modifiers: &'a str,
#[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
pub left: Span,
#[suggestion_part(code = ", {deref_right}")]
#[suggestion_part(code = "{l_modifiers}, {deref_right}")]
pub middle: Span,
#[suggestion_part(code = ")")]
#[suggestion_part(code = "{r_modifiers})")]
pub right: Span,
}

Expand All @@ -1652,11 +1654,13 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
ne: &'a str,
deref_left: &'a str,
deref_right: &'a str,
l_modifiers: &'a str,
r_modifiers: &'a str,
#[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
left: Span,
#[suggestion_part(code = ", {deref_right}")]
#[suggestion_part(code = "{l_modifiers}, {deref_right}")]
middle: Span,
#[suggestion_part(code = ")")]
#[suggestion_part(code = "{r_modifiers})")]
right: Span,
},
#[multipart_suggestion(
Expand All @@ -1670,13 +1674,15 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
deref_right: &'a str,
paren_left: &'a str,
paren_right: &'a str,
l_modifiers: &'a str,
r_modifiers: &'a str,
#[suggestion_part(code = "({deref_left}")]
left_before: Option<Span>,
#[suggestion_part(code = "{paren_left}.cast::<()>()")]
#[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")]
left_after: Span,
#[suggestion_part(code = "({deref_right}")]
right_before: Option<Span>,
#[suggestion_part(code = "{paren_right}.cast::<()>()")]
#[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")]
right_after: Span,
},
}
Expand Down
38 changes: 30 additions & 8 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,19 +670,32 @@ fn lint_wide_pointer<'tcx>(
l: &'tcx hir::Expr<'tcx>,
r: &'tcx hir::Expr<'tcx>,
) {
let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(usize, bool)> {
let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(
/* number of refs */ usize,
/* modifiers */ String,
/* is dyn */ 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(ty, _) => (!ty.is_sized(cx.tcx, cx.param_env))
.then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))),
_ => None,
}

// get the inner type of a pointer (or akin)
let mut modifiers = String::new();
ty = match ty.kind() {
ty::RawPtr(ty, _) => *ty,
ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::NonNull, def.did()) => {
modifiers.push_str(".as_ptr()");
args.type_at(0)
}
_ => return None,
};

(!ty.is_sized(cx.tcx, cx.param_env))
.then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn))))
};

// the left and right operands can have references, remove any explicit references
Expand All @@ -696,10 +709,10 @@ fn lint_wide_pointer<'tcx>(
return;
};

let Some((l_ty_refs, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else {
let Some((l_ty_refs, l_modifiers, 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 {
let Some((r_ty_refs, r_modifiers, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else {
return;
};

Expand All @@ -724,6 +737,9 @@ fn lint_wide_pointer<'tcx>(
let deref_left = &*"*".repeat(l_ty_refs);
let deref_right = &*"*".repeat(r_ty_refs);

let l_modifiers = &*l_modifiers;
let r_modifiers = &*r_modifiers;

cx.emit_span_lint(
AMBIGUOUS_WIDE_POINTER_COMPARISONS,
e.span,
Expand All @@ -733,6 +749,8 @@ fn lint_wide_pointer<'tcx>(
ne,
deref_left,
deref_right,
l_modifiers,
r_modifiers,
left,
middle,
right,
Expand All @@ -743,6 +761,8 @@ fn lint_wide_pointer<'tcx>(
ne,
deref_left,
deref_right,
l_modifiers,
r_modifiers,
left,
middle,
right,
Expand All @@ -751,6 +771,8 @@ fn lint_wide_pointer<'tcx>(
AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
deref_left,
deref_right,
l_modifiers,
r_modifiers,
paren_left: if l_ty_refs != 0 { ")" } else { "" },
paren_right: if r_ty_refs != 0 { ")" } else { "" },
left_before: (l_ty_refs != 0).then_some(l_span.shrink_to_lo()),
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/lint/wide_pointer_comparisons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::rc::Rc;
use std::sync::Arc;
use std::cmp::PartialEq;
use std::ptr::NonNull;

struct A;
struct B;
Expand Down Expand Up @@ -50,6 +51,17 @@ fn main() {
let _ = a.gt(&b);
//~^ WARN ambiguous wide pointer comparison

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

{
// &*const ?Sized
let a = &a;
Expand Down
Loading

0 comments on commit ef49365

Please sign in to comment.