1
Fork 0

Rollup merge of #78111 - SNCPlay42:not-always-self, r=lcnr

Trait predicate ambiguities are not always in `Self`

When reporting ambiguities in trait predicates, the compiler incorrectly assumed the ambiguity was always in the type the trait should be implemented on, and never the generic parameters of the trait. This caused silly suggestions for predicates like `<KnownType as Trait<_>>`, such as giving explicit types to completely unrelated variables that happened to be of type `KnownType`.

This also reverts #73027, which worked around this issue in some cases and does not appear to be necessary any more.

fixes #77982
fixes #78055
This commit is contained in:
Yuki Okushi 2020-10-20 12:11:11 +09:00 committed by GitHub
commit 3f1c637db4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 62 deletions

View file

@ -1462,9 +1462,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
let bound_predicate = predicate.bound_atom();
let mut err = match bound_predicate.skip_binder() {
ty::PredicateAtom::Trait(data, _) => {
let self_ty = data.trait_ref.self_ty();
let trait_ref = bound_predicate.rebind(data.trait_ref);
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind(), trait_ref);
debug!("trait_ref {:?}", trait_ref);
if predicate.references_error() {
return;
@ -1479,6 +1478,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
// known, since we don't dispatch based on region
// relationships.
// Pick the first substitution that still contains inference variables as the one
// we're going to emit an error for. If there are none (see above), fall back to
// the substitution for `Self`.
let subst = {
let substs = data.trait_ref.substs;
substs
.iter()
.find(|s| s.has_infer_types_or_consts())
.unwrap_or_else(|| substs[0])
};
// This is kind of a hack: it frequently happens that some earlier
// error prevents types from being fully inferred, and then we get
// a bunch of uninteresting errors saying something like "<generic
@ -1495,21 +1505,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
// check upstream for type errors and don't add the obligations to
// begin with in those cases.
if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
self.emit_inference_failure_err(
body_id,
span,
self_ty.into(),
ErrorCode::E0282,
)
.emit();
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0282).emit();
return;
}
let mut err = self.emit_inference_failure_err(
body_id,
span,
self_ty.into(),
ErrorCode::E0283,
);
let mut err =
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283);
err.note(&format!("cannot satisfy `{}`", predicate));
if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());