Skip suggestions pointing to extern macro def for assert_eq

This commit is contained in:
yukang
2026-03-30 21:55:05 +08:00
parent 584d32e3ee
commit 6518de37d4
3 changed files with 104 additions and 8 deletions
@@ -545,8 +545,12 @@ pub(super) fn suggest_dereferences(
.all(|obligation| self.predicate_may_hold(obligation))
}) && steps > 0
{
if span.in_external_macro(self.tcx.sess.source_map()) {
return false;
}
let derefs = "*".repeat(steps);
let msg = "consider dereferencing here";
let call_node = self.tcx.hir_node(*call_hir_id);
let is_receiver = matches!(
call_node,
@@ -593,7 +597,6 @@ pub(super) fn suggest_dereferences(
})
{
// Suggest dereferencing the LHS, RHS, or both terms of a binop if possible
let trait_pred = predicate.unwrap_or(trait_pred);
let lhs_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
let lhs_autoderef = (self.autoderef_steps)(lhs_ty);
@@ -644,6 +647,9 @@ pub(super) fn suggest_dereferences(
})
{
let make_sugg = |mut expr: &Expr<'_>, mut steps| {
if expr.span.in_external_macro(self.tcx.sess.source_map()) {
return None;
}
let mut prefix_span = expr.span.shrink_to_lo();
let mut msg = "consider dereferencing here";
if let hir::ExprKind::AddrOf(_, _, inner) = expr.kind {
@@ -661,10 +667,10 @@ pub(super) fn suggest_dereferences(
}
// Empty suggestions with empty spans ICE with debug assertions
if steps == 0 {
return (
return Some((
msg.trim_end_matches(" and dereferencing instead"),
vec![(prefix_span, String::new())],
);
));
}
let derefs = "*".repeat(steps);
let needs_parens = steps > 0 && expr_needs_parens(expr);
@@ -686,7 +692,7 @@ pub(super) fn suggest_dereferences(
if !prefix_span.is_empty() {
suggestion.push((prefix_span, String::new()));
}
(msg, suggestion)
Some((msg, suggestion))
};
if let Some(lsteps) = lsteps
@@ -694,8 +700,13 @@ pub(super) fn suggest_dereferences(
&& lsteps > 0
&& rsteps > 0
{
let mut suggestion = make_sugg(lhs, lsteps).1;
suggestion.append(&mut make_sugg(rhs, rsteps).1);
let Some((_, mut suggestion)) = make_sugg(lhs, lsteps) else {
return false;
};
let Some((_, mut rhs_suggestion)) = make_sugg(rhs, rsteps) else {
return false;
};
suggestion.append(&mut rhs_suggestion);
err.multipart_suggestion(
"consider dereferencing both sides of the expression",
suggestion,
@@ -705,13 +716,17 @@ pub(super) fn suggest_dereferences(
} else if let Some(lsteps) = lsteps
&& lsteps > 0
{
let (msg, suggestion) = make_sugg(lhs, lsteps);
let Some((msg, suggestion)) = make_sugg(lhs, lsteps) else {
return false;
};
err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
return true;
} else if let Some(rsteps) = rsteps
&& rsteps > 0
{
let (msg, suggestion) = make_sugg(rhs, rsteps);
let Some((msg, suggestion)) = make_sugg(rhs, rsteps) else {
return false;
};
err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
return true;
}
@@ -4815,6 +4830,9 @@ pub(super) fn suggest_convert_to_slice(
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
) {
if span.in_external_macro(self.tcx.sess.source_map()) {
return;
}
// We can only suggest the slice coercion for function and binary operation arguments,
// since the suggestion would make no sense in turbofish or call
let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
@@ -0,0 +1,23 @@
macro_rules! local_assert_ne {
($left:expr, $right:expr $(,)?) => {
match (&$left, &$right) {
(left_val, right_val) => {
if *left_val == *right_val {
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
panic!();
}
}
}
};
}
fn main() {
let buf = [0_u8; 4];
assert_ne!(buf, b"----");
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
assert_eq!(buf, b"----");
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
local_assert_ne!(buf, b"----");
}
@@ -0,0 +1,55 @@
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:16:5
|
LL | assert_ne!(buf, b"----");
| ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `[u8; 4] == &[u8; 4]`
|
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
= help: the following other types implement trait `PartialEq<Rhs>`:
`&[T]` implements `PartialEq<Vec<U, A>>`
`&[T]` implements `PartialEq<[U; N]>`
`&[u8; N]` implements `PartialEq<ByteStr>`
`&[u8; N]` implements `PartialEq<ByteString>`
`&[u8]` implements `PartialEq<ByteStr>`
`&[u8]` implements `PartialEq<ByteString>`
`&mut [T]` implements `PartialEq<Vec<U, A>>`
`&mut [T]` implements `PartialEq<[U; N]>`
and 11 others
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:19:5
|
LL | assert_eq!(buf, b"----");
| ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `[u8; 4] == &[u8; 4]`
|
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
= help: the following other types implement trait `PartialEq<Rhs>`:
`&[T]` implements `PartialEq<Vec<U, A>>`
`&[T]` implements `PartialEq<[U; N]>`
`&[u8; N]` implements `PartialEq<ByteStr>`
`&[u8; N]` implements `PartialEq<ByteString>`
`&[u8]` implements `PartialEq<ByteStr>`
`&[u8]` implements `PartialEq<ByteString>`
`&mut [T]` implements `PartialEq<Vec<U, A>>`
`&mut [T]` implements `PartialEq<[U; N]>`
and 11 others
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30
|
LL | if *left_val == *right_val {
| ^^ no implementation for `[u8; 4] == &[u8; 4]`
...
LL | local_assert_ne!(buf, b"----");
| ------------------------------ in this macro invocation
|
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
= note: this error originates in the macro `local_assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider dereferencing here
|
LL | if *left_val == **right_val {
| +
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.