1
Fork 0

Auto merge of #80828 - SNCPlay42:opaque-projections, r=estebank

Fix expected/found order on impl trait projection mismatch error

fixes #68561

This PR adds a new `ObligationCauseCode` used when checking the concrete type of an impl trait satisfies its bounds, and checks for that cause code in the existing test to see if a projection's normalized type should be the "expected" or "found" type.

The second commit adds a `peel_derives` to that test, which appears to be necessary in some cases (see projection-mismatch-in-impl-where-clause.rs, which would still give expected/found in the wrong order otherwise). This caused some other changes in diagnostics not involving impl trait, but they look correct to me.
This commit is contained in:
bors 2021-04-02 03:39:32 +00:00
commit 4fa76a4a77
18 changed files with 109 additions and 55 deletions

View file

@ -511,13 +511,18 @@ impl<T> Trait<T> for X {
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
);
if !self.suggest_constraint(
if !(self.suggest_constraining_opaque_associated_type(
db,
&msg,
proj_ty,
values.expected,
) || self.suggest_constraint(
db,
&msg,
body_owner_def_id,
proj_ty,
values.expected,
) {
)) {
db.help(&msg);
db.note(
"for more information, visit \
@ -701,20 +706,7 @@ impl<T> Trait<T> for X {
}
}
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
// When the expected `impl Trait` is not defined in the current item, it will come from
// a return type. This can occur when dealing with `TryStream` (#71035).
if self.constrain_associated_type_structured_suggestion(
db,
self.def_span(def_id),
&assoc,
proj_ty.trait_ref_and_own_substs(self).1,
values.found,
&msg,
) {
return;
}
}
self.suggest_constraining_opaque_associated_type(db, &msg, proj_ty, values.found);
if self.point_at_associated_type(db, body_owner_def_id, values.found) {
return;
@ -752,6 +744,30 @@ fn foo(&self) -> Self::T { String::new() }
}
}
/// When the expected `impl Trait` is not defined in the current item, it will come from
/// a return type. This can occur when dealing with `TryStream` (#71035).
fn suggest_constraining_opaque_associated_type(
self,
db: &mut DiagnosticBuilder<'_>,
msg: &str,
proj_ty: &ty::ProjectionTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
let assoc = self.associated_item(proj_ty.item_def_id);
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
self.constrain_associated_type_structured_suggestion(
db,
self.def_span(def_id),
&assoc,
proj_ty.trait_ref_and_own_substs(self).1,
ty,
&msg,
)
} else {
false
}
}
fn point_at_methods_that_satisfy_associated_type(
self,
db: &mut DiagnosticBuilder<'_>,