Fix trimmed_def_paths ICE in the function ptr comparison lint
This commit is contained in:
parent
c26db435bf
commit
3f105be05c
3 changed files with 75 additions and 34 deletions
|
@ -1816,14 +1816,14 @@ pub(crate) enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
|
|||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
pub(crate) enum UnpredictableFunctionPointerComparisons<'a> {
|
||||
pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> {
|
||||
#[diag(lint_unpredictable_fn_pointer_comparisons)]
|
||||
#[note(lint_note_duplicated_fn)]
|
||||
#[note(lint_note_deduplicated_fn)]
|
||||
#[note(lint_note_visit_fn_addr_eq)]
|
||||
Suggestion {
|
||||
#[subdiagnostic]
|
||||
sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a>,
|
||||
sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>,
|
||||
},
|
||||
#[diag(lint_unpredictable_fn_pointer_comparisons)]
|
||||
#[note(lint_note_duplicated_fn)]
|
||||
|
@ -1833,22 +1833,40 @@ pub(crate) enum UnpredictableFunctionPointerComparisons<'a> {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
lint_fn_addr_eq_suggestion,
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> {
|
||||
pub ne: &'a str,
|
||||
pub cast_right: String,
|
||||
pub deref_left: &'a str,
|
||||
pub deref_right: &'a str,
|
||||
#[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
|
||||
pub left: Span,
|
||||
#[suggestion_part(code = ", {deref_right}")]
|
||||
pub middle: Span,
|
||||
#[suggestion_part(code = "{cast_right})")]
|
||||
pub right: Span,
|
||||
pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> {
|
||||
#[multipart_suggestion(
|
||||
lint_fn_addr_eq_suggestion,
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
FnAddrEq {
|
||||
ne: &'a str,
|
||||
deref_left: &'a str,
|
||||
deref_right: &'a str,
|
||||
#[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
|
||||
left: Span,
|
||||
#[suggestion_part(code = ", {deref_right}")]
|
||||
middle: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
right: Span,
|
||||
},
|
||||
#[multipart_suggestion(
|
||||
lint_fn_addr_eq_suggestion,
|
||||
style = "verbose",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
FnAddrEqWithCast {
|
||||
ne: &'a str,
|
||||
deref_left: &'a str,
|
||||
deref_right: &'a str,
|
||||
fn_sig: rustc_middle::ty::PolyFnSig<'tcx>,
|
||||
#[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")]
|
||||
left: Span,
|
||||
#[suggestion_part(code = ", {deref_right}")]
|
||||
middle: Span,
|
||||
#[suggestion_part(code = " as {fn_sig})")]
|
||||
right: Span,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) struct ImproperCTypes<'a> {
|
||||
|
|
|
@ -483,29 +483,36 @@ fn lint_fn_pointer<'tcx>(
|
|||
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());
|
||||
|
||||
// We only check for a right cast as `FnDef` == `FnPtr` is not possible,
|
||||
// only `FnPtr == FnDef` is possible.
|
||||
let cast_right = if !r_ty.is_fn_ptr() {
|
||||
let fn_sig = r_ty.fn_sig(cx.tcx);
|
||||
format!(" as {fn_sig}")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let sugg =
|
||||
// We only check for a right cast as `FnDef` == `FnPtr` is not possible,
|
||||
// only `FnPtr == FnDef` is possible.
|
||||
if !r_ty.is_fn_ptr() {
|
||||
let fn_sig = r_ty.fn_sig(cx.tcx);
|
||||
|
||||
cx.emit_span_lint(
|
||||
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
|
||||
e.span,
|
||||
UnpredictableFunctionPointerComparisons::Suggestion {
|
||||
sugg: UnpredictableFunctionPointerComparisonsSuggestion {
|
||||
UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEqWithCast {
|
||||
ne,
|
||||
fn_sig,
|
||||
deref_left,
|
||||
deref_right,
|
||||
left,
|
||||
middle,
|
||||
right,
|
||||
}
|
||||
} else {
|
||||
UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEq {
|
||||
ne,
|
||||
deref_left,
|
||||
deref_right,
|
||||
left,
|
||||
middle,
|
||||
right,
|
||||
cast_right,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
cx.emit_span_lint(
|
||||
UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS,
|
||||
e.span,
|
||||
UnpredictableFunctionPointerComparisons::Suggestion { sugg },
|
||||
);
|
||||
}
|
||||
|
||||
|
|
16
tests/ui/lint/fn-ptr-comparisons-134345.rs
Normal file
16
tests/ui/lint/fn-ptr-comparisons-134345.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// This check veifies that we do not ICE when not showing a user type
|
||||
// in the suggestions/diagnostics.
|
||||
//
|
||||
// cf. https://github.com/rust-lang/rust/issues/134345
|
||||
//
|
||||
//@ check-pass
|
||||
|
||||
struct A;
|
||||
|
||||
fn fna(_a: A) {}
|
||||
|
||||
#[allow(unpredictable_function_pointer_comparisons)]
|
||||
fn main() {
|
||||
let fa: fn(A) = fna;
|
||||
let _ = fa == fna;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue