Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bb4f70c

Browse files
committedJan 18, 2021
Avoid describing a method as 'not found' when bounds are unsatisfied
Fixes #76267 When there is a single applicable method candidate, but its trait bounds are not satisfied, we avoid saying that the method is "not found". Insted, we update the error message to directly mention which bounds are not satisfied, rather than mentioning them in a note.
1 parent 4253153 commit bb4f70c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+141
-125
lines changed
 

‎compiler/rustc_errors/src/diagnostic_builder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,18 @@ macro_rules! forward {
7474
});
7575
};
7676

77-
// Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
78-
// type parameter. No obvious way to make this more generic.
77+
// Forward pattern for &mut self -> &mut Self, with generic parameters.
7978
(
8079
$(#[$attrs:meta])*
81-
pub fn $n:ident<S: Into<MultiSpan>>(
80+
pub fn $n:ident<$($generic:ident: $bound:path),*>(
8281
&mut self,
8382
$($name:ident: $ty:ty),*
8483
$(,)?
8584
) -> &mut Self
8685
) => {
8786
$(#[$attrs])*
8887
forward_inner_docs!(concat!("See [`Diagnostic::", stringify!($n), "()`].") =>
89-
pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
88+
pub fn $n<$($generic: $bound),*>(&mut self, $($name: $ty),*) -> &mut Self {
9089
self.0.diagnostic.$n($($name),*);
9190
self
9291
});
@@ -398,6 +397,7 @@ impl<'a> DiagnosticBuilder<'a> {
398397
self
399398
}
400399

400+
forward!(pub fn set_primary_message<M: Into<String>>(&mut self, msg: M) -> &mut Self);
401401
forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
402402
forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
403403

‎compiler/rustc_typeck/src/check/method/suggest.rs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
446446
}
447447
}
448448

449+
let mut label_span_not_found = || {
450+
if unsatisfied_predicates.is_empty() {
451+
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
452+
} else {
453+
err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
454+
}
455+
self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
456+
};
457+
449458
// If the method name is the name of a field with a function or closure type,
450459
// give a helping note that it has to be called as `(x.f)(...)`.
451460
if let SelfSource::MethodCall(expr) = source {
@@ -501,12 +510,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
501510
let field_kind = if is_accessible { "field" } else { "private field" };
502511
err.span_label(item_name.span, format!("{}, not a method", field_kind));
503512
} else if lev_candidate.is_none() && static_sources.is_empty() {
504-
err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
505-
self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
513+
label_span_not_found();
506514
}
507515
} else {
508-
err.span_label(span, format!("{} not found in `{}`", item_kind, ty_str));
509-
self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
516+
label_span_not_found();
510517
}
511518

512519
if self.is_fn_ty(&rcvr_ty, span) {
@@ -721,10 +728,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
721728
.map(|(_, path)| path)
722729
.collect::<Vec<_>>()
723730
.join("\n");
731+
let actual_prefix = actual.prefix_string();
732+
err.set_primary_message(&format!(
733+
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
734+
));
724735
err.note(&format!(
725-
"the method `{}` exists but the following trait bounds were not \
726-
satisfied:\n{}",
727-
item_name, bound_list
736+
"the following trait bounds were not satisfied:\n{bound_list}"
728737
));
729738
}
730739
}
@@ -742,7 +751,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
742751
);
743752
}
744753

745-
if actual.is_enum() {
754+
// Don't emit a suggestion if we found an actual method
755+
// that had unsatisfied trait bounds
756+
if unsatisfied_predicates.is_empty() && actual.is_enum() {
746757
let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
747758
if let Some(suggestion) = lev_distance::find_best_match_for_name(
748759
&adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
@@ -778,17 +789,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
778789
err.span_label(span, msg);
779790
}
780791
} else if let Some(lev_candidate) = lev_candidate {
781-
let def_kind = lev_candidate.kind.as_def_kind();
782-
err.span_suggestion(
783-
span,
784-
&format!(
785-
"there is {} {} with a similar name",
786-
def_kind.article(),
787-
def_kind.descr(lev_candidate.def_id),
788-
),
789-
lev_candidate.ident.to_string(),
790-
Applicability::MaybeIncorrect,
791-
);
792+
// Don't emit a suggestion if we found an actual method
793+
// that had unsatisfied trait bounds
794+
if unsatisfied_predicates.is_empty() {
795+
let def_kind = lev_candidate.kind.as_def_kind();
796+
err.span_suggestion(
797+
span,
798+
&format!(
799+
"there is {} {} with a similar name",
800+
def_kind.article(),
801+
def_kind.descr(lev_candidate.def_id),
802+
),
803+
lev_candidate.ident.to_string(),
804+
Applicability::MaybeIncorrect,
805+
);
806+
}
792807
}
793808

794809
return Some(err);

0 commit comments

Comments
 (0)
Please sign in to comment.