1
Fork 0

fix expected/found order on impl trait projection mismatch

This commit is contained in:
SNCPlay42 2021-01-08 22:07:49 +00:00
parent f24ce9b014
commit 770a9cf780
13 changed files with 69 additions and 46 deletions

View file

@ -323,6 +323,9 @@ pub enum ObligationCauseCode<'tcx> {
/// #[feature(trivial_bounds)] is not enabled /// #[feature(trivial_bounds)] is not enabled
TrivialBound, TrivialBound,
/// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
OpaqueType,
} }
impl ObligationCauseCode<'_> { impl ObligationCauseCode<'_> {

View file

@ -509,13 +509,18 @@ impl<T> Trait<T> for X {
"consider constraining the associated type `{}` to `{}`", "consider constraining the associated type `{}` to `{}`",
values.found, values.expected, 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, db,
&msg, &msg,
body_owner_def_id, body_owner_def_id,
proj_ty, proj_ty,
values.expected, values.expected,
) { )) {
db.help(&msg); db.help(&msg);
db.note( db.note(
"for more information, visit \ "for more information, visit \
@ -699,20 +704,7 @@ impl<T> Trait<T> for X {
} }
} }
if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { self.suggest_constraining_opaque_associated_type(db, &msg, proj_ty, values.found);
// 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;
}
}
if self.point_at_associated_type(db, body_owner_def_id, values.found) { if self.point_at_associated_type(db, body_owner_def_id, values.found) {
return; return;
@ -750,6 +742,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( fn point_at_methods_that_satisfy_associated_type(
self, self,
db: &mut DiagnosticBuilder<'_>, db: &mut DiagnosticBuilder<'_>,

View file

@ -1171,7 +1171,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
// This also instantiates nested instances of `impl Trait`. // This also instantiates nested instances of `impl Trait`.
let predicate = self.instantiate_opaque_types_in_map(predicate); let predicate = self.instantiate_opaque_types_in_map(predicate);
let cause = traits::ObligationCause::new(span, self.body_id, traits::MiscObligation); let cause = traits::ObligationCause::new(span, self.body_id, traits::OpaqueType);
// Require that the predicate holds for the concrete type. // Require that the predicate holds for the concrete type.
debug!("instantiate_opaque_types: predicate={:?}", predicate); debug!("instantiate_opaque_types: predicate={:?}", predicate);

View file

@ -1194,6 +1194,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
ObligationCauseCode::ItemObligation(_) ObligationCauseCode::ItemObligation(_)
| ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::ObjectCastObligation(_)
| ObligationCauseCode::OpaqueType
); );
if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(

View file

@ -1840,6 +1840,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
| ObligationCauseCode::MethodReceiver | ObligationCauseCode::MethodReceiver
| ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::ReturnNoExpression
| ObligationCauseCode::UnifyReceiver(..) | ObligationCauseCode::UnifyReceiver(..)
| ObligationCauseCode::OpaqueType
| ObligationCauseCode::MiscObligation => {} | ObligationCauseCode::MiscObligation => {}
ObligationCauseCode::SliceOrArrayElem => { ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type"); err.note("slice and array elements must have `Sized` type");

View file

@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32`
--> $DIR/impl-trait-return-missing-constraint.rs:25:13 --> $DIR/impl-trait-return-missing-constraint.rs:25:13
| |
LL | fn bar() -> impl Bar { LL | fn bar() -> impl Bar {
| -------- the expected opaque type | -------- the found opaque type
... ...
LL | fn baz() -> impl Bar<Item = i32> { LL | fn baz() -> impl Bar<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32` | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type
| |
= note: expected associated type `<impl Bar as Foo>::Item` = note: expected type `i32`
found type `i32` found associated type `<impl Bar as Foo>::Item`
help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32`
| |
LL | fn bar() -> impl Bar<Item = i32> { LL | fn bar() -> impl Bar<Item = i32> {

View file

@ -16,10 +16,10 @@ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-
--> $DIR/type-mismatch-signature-deduction.rs:5:13 --> $DIR/type-mismatch-signature-deduction.rs:5:13
| |
LL | fn foo() -> impl Generator<Return = i32> { LL | fn foo() -> impl Generator<Return = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result`
| |
= note: expected enum `Result<{integer}, _>` = note: expected type `i32`
found type `i32` found enum `Result<{integer}, _>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as imp
--> $DIR/bound-normalization-fail.rs:27:32 --> $DIR/bound-normalization-fail.rs:27:32
| |
LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
| |
= note: expected type `()` = note: expected associated type `<T as impl_trait::Trait>::Assoc`
found associated type `<T as impl_trait::Trait>::Assoc` found type `()`
help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()` help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
| |
LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> { LL | fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {
@ -30,10 +30,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lif
--> $DIR/bound-normalization-fail.rs:43:41 --> $DIR/bound-normalization-fail.rs:43:41
| |
LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
| |
= note: expected type `()` = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
found associated type `<T as lifetimes::Trait<'static>>::Assoc` found type `()`
help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()` help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
| |
LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> { LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output=T::Assoc> {

View file

@ -35,8 +35,10 @@ LL | let _: i32 = Leak::leak(hide(0_i32));
| |
= note: expected type `i32` = note: expected type `i32`
found associated type `<impl Foo as Leak>::T` found associated type `<impl Foo as Leak>::T`
= help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html |
LL | fn hide<T: Foo>(x: T) -> impl Foo<T = i32> {
| ^^^^^^^^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/equality2.rs:38:10 --> $DIR/equality2.rs:38:10

View file

@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'
--> $DIR/issue-70877.rs:11:12 --> $DIR/issue-70877.rs:11:12
| |
LL | type FooRet = impl std::fmt::Debug; LL | type FooRet = impl std::fmt::Debug;
| -------------------- the expected opaque type | -------------------- the found opaque type
... ...
LL | type Foo = impl Iterator<Item = FooItem>; LL | type Foo = impl Iterator<Item = FooItem>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type
| |
= note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<'
--> $DIR/issue-70877.rs:11:12 --> $DIR/issue-70877.rs:11:12
| |
LL | type FooRet = impl std::fmt::Debug; LL | type FooRet = impl std::fmt::Debug;
| -------------------- the expected opaque type | -------------------- the found opaque type
... ...
LL | type Foo = impl Iterator<Item = FooItem>; LL | type Foo = impl Iterator<Item = FooItem>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Option` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found opaque type
| |
= note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>` = note: expected struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>`
found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + 'static)>` found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> impl Debug + 'static)>`
error: aborting due to previous error error: aborting due to previous error

View file

@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28
--> $DIR/issue-63279.rs:8:16 --> $DIR/issue-63279.rs:8:16
| |
LL | type Closure = impl FnOnce(); LL | type Closure = impl FnOnce();
| ^^^^^^^^^^^^^ expected opaque type, found `()` | ^^^^^^^^^^^^^ expected `()`, found opaque type
| |
= note: expected opaque type `impl FnOnce<()>` = note: expected unit type `()`
found unit type `()` found opaque type `impl FnOnce<()>`
error: aborting due to previous error; 1 warning emitted error: aborting due to previous error; 1 warning emitted

View file

@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28
--> $DIR/issue-63279.rs:8:16 --> $DIR/issue-63279.rs:8:16
| |
LL | type Closure = impl FnOnce(); LL | type Closure = impl FnOnce();
| ^^^^^^^^^^^^^ expected opaque type, found `()` | ^^^^^^^^^^^^^ expected `()`, found opaque type
| |
= note: expected opaque type `impl FnOnce<()>` = note: expected unit type `()`
found unit type `()` found opaque type `impl FnOnce<()>`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors