diff options
13 files changed, 69 insertions, 46 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 0bd0a701fb2..3650866c007 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -323,6 +323,9 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, + + /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` + OpaqueType, } impl ObligationCauseCode<'_> { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index f19cc998449..8ff84b0e743 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -509,13 +509,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 \ @@ -699,20 +704,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; @@ -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( self, db: &mut DiagnosticBuilder<'_>, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index d6a585e626c..186256101e4 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1171,7 +1171,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // This also instantiates nested instances of `impl Trait`. 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. debug!("instantiate_opaque_types: predicate={:?}", predicate); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index a3faf4cb7d4..5de4fb1ce8c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1194,6 +1194,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ObjectCastObligation(_) + | ObligationCauseCode::OpaqueType ); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c1b105f1d84..6292413d7bd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1840,6 +1840,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::UnifyReceiver(..) + | ObligationCauseCode::OpaqueType | ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index b0e9e33a6c3..89e05b61fc9 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<impl Bar as Foo>::Item == i32` --> $DIR/impl-trait-return-missing-constraint.rs:25:13 | LL | fn bar() -> impl Bar { - | -------- the expected opaque type + | -------- the found opaque type ... 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` - found type `i32` + = note: expected type `i32` + found associated type `<impl Bar as Foo>::Item` help: consider constraining the associated type `<impl Bar as Foo>::Item` to `i32` | LL | fn bar() -> impl Bar<Item = i32> { diff --git a/src/test/ui/generator/type-mismatch-signature-deduction.stderr b/src/test/ui/generator/type-mismatch-signature-deduction.stderr index 30e23ea8f65..3f1f33a3b12 100644 --- a/src/test/ui/generator/type-mismatch-signature-deduction.stderr +++ b/src/test/ui/generator/type-mismatch-signature-deduction.stderr @@ -16,10 +16,10 @@ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature- --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Generator<Return = i32> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found enum `Result` | - = note: expected enum `Result<{integer}, _>` - found type `i32` + = note: expected type `i32` + found enum `Result<{integer}, _>` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index a7d06c71663..6958cd97a4a 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as imp --> $DIR/bound-normalization-fail.rs:27:32 | LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | - = note: expected type `()` - found associated type `<T as impl_trait::Trait>::Assoc` + = note: expected associated type `<T as impl_trait::Trait>::Assoc` + found type `()` 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> { @@ -30,10 +30,10 @@ error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lif --> $DIR/bound-normalization-fail.rs:43:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()` | - = note: expected type `()` - found associated type `<T as lifetimes::Trait<'static>>::Assoc` + = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc` + found type `()` 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> { diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr index 1443b76048b..3318866c52c 100644 --- a/src/test/ui/impl-trait/equality2.stderr +++ b/src/test/ui/impl-trait/equality2.stderr @@ -35,8 +35,10 @@ LL | let _: i32 = Leak::leak(hide(0_i32)); | = note: expected type `i32` found associated type `<impl Foo as Leak>::T` - = 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 +help: consider constraining the associated type `<impl Foo as Leak>::T` to `i32` + | +LL | fn hide<T: Foo>(x: T) -> impl Foo<T = i32> { + | ^^^^^^^^^ error[E0308]: mismatched types --> $DIR/equality2.rs:38:10 diff --git a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr index bd4d4fdf2a6..8e42b9d46db 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.full_tait.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<' --> $DIR/issue-70877.rs:11:12 | LL | type FooRet = impl std::fmt::Debug; - | -------------------- the expected opaque type + | -------------------- the found opaque type ... 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)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + '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)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr index bd4d4fdf2a6..8e42b9d46db 100644 --- a/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr +++ b/src/test/ui/impl-trait/issues/issue-70877.min_tait.stderr @@ -2,13 +2,13 @@ error[E0271]: type mismatch resolving `<Bar as Iterator>::Item == Box<(dyn for<' --> $DIR/issue-70877.rs:11:12 | LL | type FooRet = impl std::fmt::Debug; - | -------------------- the expected opaque type + | -------------------- the found opaque type ... 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)>` - found struct `Box<(dyn for<'r> Fn(&'r (dyn ToString + 'r)) -> Option<String> + '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)) -> impl Debug + 'static)>` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr index f544f61df97..53a0016c08e 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.full_tait.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28 --> $DIR/issue-63279.rs:8:16 | LL | type Closure = impl FnOnce(); - | ^^^^^^^^^^^^^ expected opaque type, found `()` + | ^^^^^^^^^^^^^ expected `()`, found opaque type | - = note: expected opaque type `impl FnOnce<()>` - found unit type `()` + = note: expected unit type `()` + found opaque type `impl FnOnce<()>` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr index bdf414d0bad..be386ab90ea 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.min_tait.stderr @@ -11,10 +11,10 @@ error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:11:5: 11:28 --> $DIR/issue-63279.rs:8:16 | LL | type Closure = impl FnOnce(); - | ^^^^^^^^^^^^^ expected opaque type, found `()` + | ^^^^^^^^^^^^^ expected `()`, found opaque type | - = note: expected opaque type `impl FnOnce<()>` - found unit type `()` + = note: expected unit type `()` + found opaque type `impl FnOnce<()>` error: aborting due to 2 previous errors |
