Skip to content

Commit a28a275

Browse files
authored
Rollup merge of #154551 - chenyukang:yukang-fix-146204-assert-ne-suggestion-span, r=JohnTitor
Skip suggestions pointing to macro def for assert_eq Fixes #146204 It's better to suggest: ```console help: consider borrowing here --> src/main.rs:3:16 | 3| assert_ne!(&buf, b"----"); | + ``` but i don't want to give a too heuristic but not general enough fix, let suppress them.
2 parents f5f76ab + 6518de3 commit a28a275

3 files changed

Lines changed: 104 additions & 8 deletions

File tree

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
545545
.all(|obligation| self.predicate_may_hold(obligation))
546546
}) && steps > 0
547547
{
548+
if span.in_external_macro(self.tcx.sess.source_map()) {
549+
return false;
550+
}
548551
let derefs = "*".repeat(steps);
549552
let msg = "consider dereferencing here";
553+
550554
let call_node = self.tcx.hir_node(*call_hir_id);
551555
let is_receiver = matches!(
552556
call_node,
@@ -593,7 +597,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
593597
})
594598
{
595599
// Suggest dereferencing the LHS, RHS, or both terms of a binop if possible
596-
597600
let trait_pred = predicate.unwrap_or(trait_pred);
598601
let lhs_ty = self.tcx.instantiate_bound_regions_with_erased(trait_pred.self_ty());
599602
let lhs_autoderef = (self.autoderef_steps)(lhs_ty);
@@ -644,6 +647,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
644647
})
645648
{
646649
let make_sugg = |mut expr: &Expr<'_>, mut steps| {
650+
if expr.span.in_external_macro(self.tcx.sess.source_map()) {
651+
return None;
652+
}
647653
let mut prefix_span = expr.span.shrink_to_lo();
648654
let mut msg = "consider dereferencing here";
649655
if let hir::ExprKind::AddrOf(_, _, inner) = expr.kind {
@@ -661,10 +667,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
661667
}
662668
// Empty suggestions with empty spans ICE with debug assertions
663669
if steps == 0 {
664-
return (
670+
return Some((
665671
msg.trim_end_matches(" and dereferencing instead"),
666672
vec![(prefix_span, String::new())],
667-
);
673+
));
668674
}
669675
let derefs = "*".repeat(steps);
670676
let needs_parens = steps > 0 && expr_needs_parens(expr);
@@ -686,16 +692,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
686692
if !prefix_span.is_empty() {
687693
suggestion.push((prefix_span, String::new()));
688694
}
689-
(msg, suggestion)
695+
Some((msg, suggestion))
690696
};
691697

692698
if let Some(lsteps) = lsteps
693699
&& let Some(rsteps) = rsteps
694700
&& lsteps > 0
695701
&& rsteps > 0
696702
{
697-
let mut suggestion = make_sugg(lhs, lsteps).1;
698-
suggestion.append(&mut make_sugg(rhs, rsteps).1);
703+
let Some((_, mut suggestion)) = make_sugg(lhs, lsteps) else {
704+
return false;
705+
};
706+
let Some((_, mut rhs_suggestion)) = make_sugg(rhs, rsteps) else {
707+
return false;
708+
};
709+
suggestion.append(&mut rhs_suggestion);
699710
err.multipart_suggestion(
700711
"consider dereferencing both sides of the expression",
701712
suggestion,
@@ -705,13 +716,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
705716
} else if let Some(lsteps) = lsteps
706717
&& lsteps > 0
707718
{
708-
let (msg, suggestion) = make_sugg(lhs, lsteps);
719+
let Some((msg, suggestion)) = make_sugg(lhs, lsteps) else {
720+
return false;
721+
};
709722
err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
710723
return true;
711724
} else if let Some(rsteps) = rsteps
712725
&& rsteps > 0
713726
{
714-
let (msg, suggestion) = make_sugg(rhs, rsteps);
727+
let Some((msg, suggestion)) = make_sugg(rhs, rsteps) else {
728+
return false;
729+
};
715730
err.multipart_suggestion(msg, suggestion, Applicability::MachineApplicable);
716731
return true;
717732
}
@@ -4824,6 +4839,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
48244839
candidate_impls: &[ImplCandidate<'tcx>],
48254840
span: Span,
48264841
) {
4842+
if span.in_external_macro(self.tcx.sess.source_map()) {
4843+
return;
4844+
}
48274845
// We can only suggest the slice coercion for function and binary operation arguments,
48284846
// since the suggestion would make no sense in turbofish or call
48294847
let (ObligationCauseCode::BinOp { .. } | ObligationCauseCode::FunctionArg { .. }) =
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
macro_rules! local_assert_ne {
2+
($left:expr, $right:expr $(,)?) => {
3+
match (&$left, &$right) {
4+
(left_val, right_val) => {
5+
if *left_val == *right_val {
6+
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
7+
panic!();
8+
}
9+
}
10+
}
11+
};
12+
}
13+
14+
fn main() {
15+
let buf = [0_u8; 4];
16+
assert_ne!(buf, b"----");
17+
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
18+
19+
assert_eq!(buf, b"----");
20+
//~^ ERROR can't compare `[u8; 4]` with `&[u8; 4]`
21+
22+
local_assert_ne!(buf, b"----");
23+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
2+
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:16:5
3+
|
4+
LL | assert_ne!(buf, b"----");
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `[u8; 4] == &[u8; 4]`
6+
|
7+
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
8+
= help: the following other types implement trait `PartialEq<Rhs>`:
9+
`&[T]` implements `PartialEq<Vec<U, A>>`
10+
`&[T]` implements `PartialEq<[U; N]>`
11+
`&[u8; N]` implements `PartialEq<ByteStr>`
12+
`&[u8; N]` implements `PartialEq<ByteString>`
13+
`&[u8]` implements `PartialEq<ByteStr>`
14+
`&[u8]` implements `PartialEq<ByteString>`
15+
`&mut [T]` implements `PartialEq<Vec<U, A>>`
16+
`&mut [T]` implements `PartialEq<[U; N]>`
17+
and 11 others
18+
19+
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
20+
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:19:5
21+
|
22+
LL | assert_eq!(buf, b"----");
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `[u8; 4] == &[u8; 4]`
24+
|
25+
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
26+
= help: the following other types implement trait `PartialEq<Rhs>`:
27+
`&[T]` implements `PartialEq<Vec<U, A>>`
28+
`&[T]` implements `PartialEq<[U; N]>`
29+
`&[u8; N]` implements `PartialEq<ByteStr>`
30+
`&[u8; N]` implements `PartialEq<ByteString>`
31+
`&[u8]` implements `PartialEq<ByteStr>`
32+
`&[u8]` implements `PartialEq<ByteString>`
33+
`&mut [T]` implements `PartialEq<Vec<U, A>>`
34+
`&mut [T]` implements `PartialEq<[U; N]>`
35+
and 11 others
36+
37+
error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]`
38+
--> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30
39+
|
40+
LL | if *left_val == *right_val {
41+
| ^^ no implementation for `[u8; 4] == &[u8; 4]`
42+
...
43+
LL | local_assert_ne!(buf, b"----");
44+
| ------------------------------ in this macro invocation
45+
|
46+
= help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]`
47+
= note: this error originates in the macro `local_assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info)
48+
help: consider dereferencing here
49+
|
50+
LL | if *left_val == **right_val {
51+
| +
52+
53+
error: aborting due to 3 previous errors
54+
55+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)