From 6fa58be8f463e25cc6b8219ea1db44a466cddc68 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 29 Feb 2024 21:24:09 +0100 Subject: [PATCH 1/6] add test for assoc type mismatch in supertrait --- tests/ui/trait-bounds/super-assoc-mismatch.rs | 41 ++++ .../trait-bounds/super-assoc-mismatch.stderr | 188 ++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 tests/ui/trait-bounds/super-assoc-mismatch.rs create mode 100644 tests/ui/trait-bounds/super-assoc-mismatch.stderr diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs new file mode 100644 index 0000000000000..1cfcb5c8ceb2f --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -0,0 +1,41 @@ +trait Super { + type Assoc; +} +impl Super for () { + type Assoc = u8; +} +trait Sub: Super {} + +trait BoundOnSelf: Sub {} +impl BoundOnSelf for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied +//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` + +trait BoundOnParam {} +impl BoundOnParam<()> for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied +//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` + +trait BoundOnAssoc { + type Assoc: Sub; +} +impl BoundOnAssoc for () { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied + //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` +} + +trait BoundOnGat where Self::Assoc: Sub { + type Assoc; +} +impl BoundOnGat for u8 { + //~^ ERROR type mismatch resolving `<() as Super>::Assoc == u16` + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +fn trivial_bound() where (): Sub {} +//~^ ERROR the trait bound `(): Sub` is not satisfied +//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` + +fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr new file mode 100644 index 0000000000000..278c655d0fdca --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -0,0 +1,188 @@ +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:10:22 + | +LL | impl BoundOnSelf for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnSelf` + --> $DIR/super-assoc-mismatch.rs:9:20 + | +LL | trait BoundOnSelf: Sub {} + | ^^^ required by this bound in `BoundOnSelf` + +error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` + --> $DIR/super-assoc-mismatch.rs:10:6 + | +LL | impl BoundOnSelf for () {} + | ^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | +note: expected this to be `u16` + --> $DIR/super-assoc-mismatch.rs:5:18 + | +LL | type Assoc = u8; + | ^^ +note: required for `()` to implement `Sub` + --> $DIR/super-assoc-mismatch.rs:7:7 + | +LL | trait Sub: Super {} + | ^^^ +note: required by a bound in `BoundOnSelf` + --> $DIR/super-assoc-mismatch.rs:9:20 + | +LL | trait BoundOnSelf: Sub {} + | ^^^ required by this bound in `BoundOnSelf` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:15:27 + | +LL | impl BoundOnParam<()> for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnParam` + --> $DIR/super-assoc-mismatch.rs:14:23 + | +LL | trait BoundOnParam {} + | ^^^ required by this bound in `BoundOnParam` + +error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` + --> $DIR/super-assoc-mismatch.rs:15:6 + | +LL | impl BoundOnParam<()> for () {} + | ^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | +note: expected this to be `u16` + --> $DIR/super-assoc-mismatch.rs:5:18 + | +LL | type Assoc = u8; + | ^^ +note: required for `()` to implement `Sub` + --> $DIR/super-assoc-mismatch.rs:7:7 + | +LL | trait Sub: Super {} + | ^^^ +note: required by a bound in `BoundOnParam` + --> $DIR/super-assoc-mismatch.rs:14:23 + | +LL | trait BoundOnParam {} + | ^^^ required by this bound in `BoundOnParam` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:23:18 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnAssoc::Assoc` + --> $DIR/super-assoc-mismatch.rs:20:17 + | +LL | type Assoc: Sub; + | ^^^ required by this bound in `BoundOnAssoc::Assoc` + +error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` + --> $DIR/super-assoc-mismatch.rs:23:18 + | +LL | type Assoc = (); + | ^^ type mismatch resolving `<() as Super>::Assoc == u16` + | +note: expected this to be `u16` + --> $DIR/super-assoc-mismatch.rs:5:18 + | +LL | type Assoc = u8; + | ^^ +note: required for `<() as BoundOnAssoc>::Assoc` to implement `Sub` + --> $DIR/super-assoc-mismatch.rs:7:7 + | +LL | trait Sub: Super {} + | ^^^ +note: required by a bound in `BoundOnAssoc::Assoc` + --> $DIR/super-assoc-mismatch.rs:20:17 + | +LL | type Assoc: Sub; + | ^^^ required by this bound in `BoundOnAssoc::Assoc` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:33:21 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnGat` + --> $DIR/super-assoc-mismatch.rs:28:41 + | +LL | trait BoundOnGat where Self::Assoc: Sub { + | ^^^ required by this bound in `BoundOnGat` + +error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` + --> $DIR/super-assoc-mismatch.rs:31:6 + | +LL | impl BoundOnGat for u8 { + | ^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | +note: expected this to be `u16` + --> $DIR/super-assoc-mismatch.rs:5:18 + | +LL | type Assoc = u8; + | ^^ +note: required for `::Assoc` to implement `Sub` + --> $DIR/super-assoc-mismatch.rs:7:7 + | +LL | trait Sub: Super {} + | ^^^ +note: required by a bound in `BoundOnGat` + --> $DIR/super-assoc-mismatch.rs:28:41 + | +LL | trait BoundOnGat where Self::Assoc: Sub { + | ^^^ required by this bound in `BoundOnGat` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:37:26 + | +LL | fn trivial_bound() where (): Sub {} + | ^^^^^^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` + --> $DIR/super-assoc-mismatch.rs:37:26 + | +LL | fn trivial_bound() where (): Sub {} + | ^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | +note: expected this to be `u8` + --> $DIR/super-assoc-mismatch.rs:5:18 + | +LL | type Assoc = u8; + | ^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. From 189e7843e80db90ee5283c82c2d2e0ee9fd7b6b5 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 8 Feb 2024 16:56:47 +0100 Subject: [PATCH 2/6] adjust obligation spans for super projections --- .../rustc_hir_analysis/src/check/wfcheck.rs | 16 +++- .../rustc_trait_selection/src/traits/wf.rs | 92 ++++++++++++------- .../hr-associated-type-projection-1.rs | 2 +- .../hr-associated-type-projection-1.stderr | 8 +- tests/ui/trait-bounds/super-assoc-mismatch.rs | 2 +- .../trait-bounds/super-assoc-mismatch.stderr | 16 ++-- 6 files changed, 84 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f03d0f8a88529..17222922d3e8b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1294,8 +1294,9 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; + let trait_span = ast_trait_ref.path.span; let trait_ref = wfcx.normalize( - ast_trait_ref.path.span, + trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); @@ -1306,12 +1307,21 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_def_id, trait_pred, - ast_trait_ref.path.span, + trait_span, item, ); for obligation in &mut obligations { + if obligation.cause.span != trait_span { + // We already have a better span. + continue; + } if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() - && pred.self_ty().skip_binder() == trait_ref.self_ty() + && pred.skip_binder().self_ty() == trait_ref.self_ty() + { + obligation.cause.span = ast_self_ty.span; + } + if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + && pred.skip_binder().self_ty() == trait_ref.self_ty() { obligation.cause.span = ast_self_ty.span; } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 15059bc661396..4cbdadac770a6 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -223,60 +223,84 @@ enum Elaborate { None, } +/// Points the cause span of a super predicate at the relevant associated type. +/// +/// Given a trait impl item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// } +/// ``` +/// +/// And a super predicate of `TargetTrait` that has any of the following forms: +/// +/// 1. `::Assoc = ::Assoc` +/// 2. `<::Assoc as OtherTrait>::Assoc = OtherType` +/// 3. `::Assoc: OtherTrait` +/// +/// Replace the span of the cause with the span of the associated item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// // ^^^^^^^^ this span +/// } +/// ``` +/// +/// Note that bounds that can be expressed as associated item bounds are **not** +/// super predicates. This means that form 2 and 3 from above are only relevant if +/// the [`GenericArgsRef`] of the projection type are not its identity arguments. fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: ty::Predicate<'tcx>, ) { - debug!( - "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", - trait_ref, item, cause, pred - ); + debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation"); let (items, impl_def_id) = match item { Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { (impl_.items, *owner_id) } _ => return, }; - let fix_span = - |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { - hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span, - _ => impl_item_ref.span, - }; + + let ty_to_impl_span = |ty: Ty<'_>| { + if let ty::Alias(ty::Projection, projection_ty) = ty.kind() + && let Some(&impl_item_id) = + tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) + && let Some(impl_item) = + items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id) + { + Some(tcx.hir().impl_item(impl_item.id).expect_type().span) + } else { + None + } + }; // It is fine to skip the binder as we don't care about regions here. match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { - // The obligation comes not from the current `impl` nor the `trait` being implemented, - // but rather from a "second order" obligation, where an associated type has a - // projection coming from another associated type. See - // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and - // `traits-assoc-type-in-supertrait-bad.rs`. - if let Some(ty::Alias(ty::Projection, projection_ty)) = - proj.term.ty().map(|ty| ty.kind()) - && let Some(&impl_item_id) = - tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) + // Form 1: The obligation comes not from the current `impl` nor the `trait` being + // implemented, but rather from a "second order" obligation, where an associated + // type has a projection coming from another associated type. + // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example. + if let Some(term_ty) = proj.term.ty() + && let Some(impl_item_span) = ty_to_impl_span(term_ty) { cause.span = impl_item_span; } + + // Form 2: A projection obligation for an associated item failed to be met. + if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) { + cause.span = impl_item_span; + } } + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - // An associated item obligation born out of the `trait` failed to be met. An example - // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. + // Form 3: A trait obligation for an associated item failed to be met. debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); - if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind() - && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) - { + if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) { cause.span = impl_item_span; } } @@ -355,9 +379,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCauseCode::DerivedObligation, ); } - extend_cause_with_original_assoc_item_obligation( - tcx, trait_ref, item, &mut cause, predicate, - ); + extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate); traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) }; diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs index 3df3f68ab1eed..d7fc5d122c3ec 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.rs +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,8 +11,8 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ type mismatch resolving `::Target == T` type Item = T; + //~^ type mismatch resolving `::Target == T` } pub fn main() { diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index 65221718ee661..b871bb51ae313 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,10 +1,10 @@ error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:33 + --> $DIR/hr-associated-type-projection-1.rs:14:17 | LL | impl UnsafeCopy<'_, T> for T { - | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | expected this type parameter + | - expected this type parameter +LL | type Item = T; + | ^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs index 1cfcb5c8ceb2f..b701f0b3f88da 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.rs +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -29,9 +29,9 @@ trait BoundOnGat where Self::Assoc: Sub { type Assoc; } impl BoundOnGat for u8 { - //~^ ERROR type mismatch resolving `<() as Super>::Assoc == u16` type Assoc = (); //~^ ERROR the trait bound `(): Sub` is not satisfied + //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` } fn trivial_bound() where (): Sub {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr index 278c655d0fdca..bf19dd45193ff 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -16,10 +16,10 @@ LL | trait BoundOnSelf: Sub {} | ^^^ required by this bound in `BoundOnSelf` error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:10:6 + --> $DIR/super-assoc-mismatch.rs:10:22 | LL | impl BoundOnSelf for () {} - | ^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | ^^ type mismatch resolving `<() as Super>::Assoc == u16` | note: expected this to be `u16` --> $DIR/super-assoc-mismatch.rs:5:18 @@ -55,10 +55,10 @@ LL | trait BoundOnParam {} | ^^^ required by this bound in `BoundOnParam` error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:15:6 + --> $DIR/super-assoc-mismatch.rs:15:27 | LL | impl BoundOnParam<()> for () {} - | ^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` + | ^^ type mismatch resolving `<() as Super>::Assoc == u16` | note: expected this to be `u16` --> $DIR/super-assoc-mismatch.rs:5:18 @@ -116,7 +116,7 @@ LL | type Assoc: Sub; | ^^^ required by this bound in `BoundOnAssoc::Assoc` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:33:21 + --> $DIR/super-assoc-mismatch.rs:32:21 | LL | type Assoc = (); | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` @@ -133,10 +133,10 @@ LL | trait BoundOnGat where Self::Assoc: Sub { | ^^^ required by this bound in `BoundOnGat` error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:31:6 + --> $DIR/super-assoc-mismatch.rs:32:21 | -LL | impl BoundOnGat for u8 { - | ^^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` +LL | type Assoc = (); + | ^^ type mismatch resolving `<() as Super>::Assoc == u16` | note: expected this to be `u16` --> $DIR/super-assoc-mismatch.rs:5:18 From 443c81626103e3f6c03e9ea681c81a3f737312e8 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 1 Mar 2024 12:33:14 +0100 Subject: [PATCH 3/6] rename `ast_*` to `hir_*` in wfcheck --- .../rustc_hir_analysis/src/check/wfcheck.rs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 17222922d3e8b..f5d0939077da5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -296,31 +296,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, hir_generics) => { let res = check_type_defn(tcx, item, false); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } hir::ItemKind::Trait(..) => check_trait(tcx, item), hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, ast_generics) => { + hir::ItemKind::TyAlias(hir_ty, hir_generics) => { if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } else { Ok(()) @@ -1277,16 +1277,16 @@ fn check_item_type( }) } -#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] +#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - ast_self_ty: &hir::Ty<'_>, - ast_trait_ref: &Option>, + hir_self_ty: &hir::Ty<'_>, + hir_trait_ref: &Option>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - match ast_trait_ref { - Some(ast_trait_ref) => { + match hir_trait_ref { + Some(hir_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). @@ -1294,7 +1294,7 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; - let trait_span = ast_trait_ref.path.span; + let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), @@ -1318,12 +1318,12 @@ fn check_impl<'tcx>( if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; } if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; } } debug!(?obligations); @@ -1337,7 +1337,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - ast_self_ty.span, + hir_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); From aa55f6daa2c83020a271077bb15590755f4119d9 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 1 Mar 2024 17:19:16 +0100 Subject: [PATCH 4/6] suppress fulfillment errors for super projections --- .../error_reporting/type_err_ctxt_ext.rs | 69 +++++----- tests/ui/issues/issue-33941.rs | 1 - tests/ui/issues/issue-33941.stderr | 12 +- tests/ui/trait-bounds/super-assoc-mismatch.rs | 5 - .../trait-bounds/super-assoc-mismatch.stderr | 121 ++---------------- 5 files changed, 48 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 62933bce76b77..129ddb089bd03 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1389,38 +1389,45 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return true; } - // FIXME: It should be possible to deal with `ForAll` in a cleaner way. - let bound_error = error.kind(); - let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), - ) => (cond, bound_error.rebind(error)), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for pred in elaborate(self.tcx, std::iter::once(cond)) { - let bound_predicate = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = - bound_predicate.skip_binder() - { - let error = error.to_poly_trait_ref(); - let implication = bound_predicate.rebind(implication.trait_ref); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication) { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } + if let Some(error) = error.to_opt_poly_trait_pred() { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .any(|implied| { + if error.polarity() != implied.polarity() { + return false; + } + let error = error.to_poly_trait_ref(); + let implied = implied.to_poly_trait_ref(); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(); + let is_implied = self.can_sub(param_env, error, implied); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied + }) + } else if let Some(error) = error.to_opt_poly_projection_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_projection_pred()) + .any(|implied| { + self.enter_forall(implied, |implied| { + let param_env = ty::ParamEnv::empty(); + let is_implied = + self.can_eq(param_env, error.projection_ty, implied.projection_ty) + && self.can_eq(param_env, error.term, implied.term); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied + }) + }) + }) + } else { + false } - - false } #[instrument(skip(self), level = "debug")] diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 0ad7cbe8efc41..7b5be30834b9d 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -5,5 +5,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr index e7f4a4fa004ce..f1b6b6ba17edc 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.stderr @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned>` to implement `Iterator` = note: required for `Cloned>` to implement `IntoIterator` -error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_` - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required for `Cloned>` to implement `Iterator` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs index b701f0b3f88da..00a9df35b002d 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.rs +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -9,12 +9,10 @@ trait Sub: Super {} trait BoundOnSelf: Sub {} impl BoundOnSelf for () {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` trait BoundOnParam {} impl BoundOnParam<()> for () {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` trait BoundOnAssoc { type Assoc: Sub; @@ -22,7 +20,6 @@ trait BoundOnAssoc { impl BoundOnAssoc for () { type Assoc = (); //~^ ERROR the trait bound `(): Sub` is not satisfied - //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` } trait BoundOnGat where Self::Assoc: Sub { @@ -31,11 +28,9 @@ trait BoundOnGat where Self::Assoc: Sub { impl BoundOnGat for u8 { type Assoc = (); //~^ ERROR the trait bound `(): Sub` is not satisfied - //~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` } fn trivial_bound() where (): Sub {} //~^ ERROR the trait bound `(): Sub` is not satisfied -//~| ERROR type mismatch resolving `<() as Super>::Assoc == u16` fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr index bf19dd45193ff..0ce0b66cbf909 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -15,30 +15,8 @@ note: required by a bound in `BoundOnSelf` LL | trait BoundOnSelf: Sub {} | ^^^ required by this bound in `BoundOnSelf` -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:10:22 - | -LL | impl BoundOnSelf for () {} - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `()` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnSelf` - --> $DIR/super-assoc-mismatch.rs:9:20 - | -LL | trait BoundOnSelf: Sub {} - | ^^^ required by this bound in `BoundOnSelf` - error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:15:27 + --> $DIR/super-assoc-mismatch.rs:14:27 | LL | impl BoundOnParam<()> for () {} | ^^ the trait `Sub` is not implemented for `()` @@ -49,35 +27,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnParam` - --> $DIR/super-assoc-mismatch.rs:14:23 - | -LL | trait BoundOnParam {} - | ^^^ required by this bound in `BoundOnParam` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:15:27 - | -LL | impl BoundOnParam<()> for () {} - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `()` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnParam` - --> $DIR/super-assoc-mismatch.rs:14:23 + --> $DIR/super-assoc-mismatch.rs:13:23 | LL | trait BoundOnParam {} | ^^^ required by this bound in `BoundOnParam` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:23:18 + --> $DIR/super-assoc-mismatch.rs:21:18 | LL | type Assoc = (); | ^^ the trait `Sub` is not implemented for `()` @@ -88,35 +44,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnAssoc::Assoc` - --> $DIR/super-assoc-mismatch.rs:20:17 - | -LL | type Assoc: Sub; - | ^^^ required by this bound in `BoundOnAssoc::Assoc` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:23:18 - | -LL | type Assoc = (); - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `<() as BoundOnAssoc>::Assoc` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnAssoc::Assoc` - --> $DIR/super-assoc-mismatch.rs:20:17 + --> $DIR/super-assoc-mismatch.rs:18:17 | LL | type Assoc: Sub; | ^^^ required by this bound in `BoundOnAssoc::Assoc` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:32:21 + --> $DIR/super-assoc-mismatch.rs:29:21 | LL | type Assoc = (); | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` @@ -127,35 +61,13 @@ help: this trait has no implementations, consider adding one LL | trait Sub: Super {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `BoundOnGat` - --> $DIR/super-assoc-mismatch.rs:28:41 - | -LL | trait BoundOnGat where Self::Assoc: Sub { - | ^^^ required by this bound in `BoundOnGat` - -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:32:21 - | -LL | type Assoc = (); - | ^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u16` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ -note: required for `::Assoc` to implement `Sub` - --> $DIR/super-assoc-mismatch.rs:7:7 - | -LL | trait Sub: Super {} - | ^^^ -note: required by a bound in `BoundOnGat` - --> $DIR/super-assoc-mismatch.rs:28:41 + --> $DIR/super-assoc-mismatch.rs:25:41 | LL | trait BoundOnGat where Self::Assoc: Sub { | ^^^ required by this bound in `BoundOnGat` error[E0277]: the trait bound `(): Sub` is not satisfied - --> $DIR/super-assoc-mismatch.rs:37:26 + --> $DIR/super-assoc-mismatch.rs:33:26 | LL | fn trivial_bound() where (): Sub {} | ^^^^^^^ the trait `Sub` is not implemented for `()` @@ -168,21 +80,6 @@ LL | trait Sub: Super {} = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable -error[E0271]: type mismatch resolving `<() as Super>::Assoc == u16` - --> $DIR/super-assoc-mismatch.rs:37:26 - | -LL | fn trivial_bound() where (): Sub {} - | ^^^^^^^ type mismatch resolving `<() as Super>::Assoc == u16` - | -note: expected this to be `u8` - --> $DIR/super-assoc-mismatch.rs:5:18 - | -LL | type Assoc = u8; - | ^^ - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable - -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. From 6bd970d585816ced1fba673401e6b9e3a566662a Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 4 Mar 2024 21:06:16 +0100 Subject: [PATCH 5/6] address review feedback --- .../error_reporting/type_err_ctxt_ext.rs | 79 ++++++++++++------- .../rustc_trait_selection/src/traits/wf.rs | 7 +- tests/ui/trait-bounds/super-assoc-mismatch.rs | 24 ++++++ .../trait-bounds/super-assoc-mismatch.stderr | 22 +++++- 4 files changed, 101 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 129ddb089bd03..c2059230bfcaa 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1382,6 +1382,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] impl<'tcx> TypeErrCtxt<'_, 'tcx> { + fn can_match_trait( + &self, + goal: ty::TraitPredicate<'tcx>, + assumption: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + if goal.polarity != assumption.polarity() { + return false; + } + + let trait_goal = goal.trait_ref; + let trait_assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption.to_poly_trait_ref(), + ); + + self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption) + } + + fn can_match_projection( + &self, + goal: ty::ProjectionPredicate<'tcx>, + assumption: ty::PolyProjectionPredicate<'tcx>, + ) -> bool { + let assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption, + ); + + let param_env = ty::ParamEnv::empty(); + self.can_eq(param_env, goal.projection_ty, assumption.projection_ty) + && self.can_eq(param_env, goal.term, assumption.term) + } + // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { @@ -1390,39 +1425,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } if let Some(error) = error.to_opt_poly_trait_pred() { - elaborate(self.tcx, std::iter::once(cond)) - .filter_map(|implied| implied.to_opt_poly_trait_pred()) - .any(|implied| { - if error.polarity() != implied.polarity() { - return false; - } - let error = error.to_poly_trait_ref(); - let implied = implied.to_poly_trait_ref(); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - let is_implied = self.can_sub(param_env, error, implied); - if is_implied { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); - } - is_implied - }) + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .any(|implied| { + let is_implied = self.can_match_trait(error, implied); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied + }) + }) } else if let Some(error) = error.to_opt_poly_projection_pred() { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond)) .filter_map(|implied| implied.to_opt_poly_projection_pred()) .any(|implied| { - self.enter_forall(implied, |implied| { - let param_env = ty::ParamEnv::empty(); - let is_implied = - self.can_eq(param_env, error.projection_ty, implied.projection_ty) - && self.can_eq(param_env, error.term, implied.term); - if is_implied { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); - } - is_implied - }) + let is_implied = self.can_match_projection(error, implied); + if is_implied { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); + } + is_implied }) }) } else { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 4cbdadac770a6..b09a803e856d2 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -235,8 +235,8 @@ enum Elaborate { /// /// And a super predicate of `TargetTrait` that has any of the following forms: /// -/// 1. `::Assoc = ::Assoc` -/// 2. `<::Assoc as OtherTrait>::Assoc = OtherType` +/// 1. `::Assoc == ::Assoc` +/// 2. `<::Assoc as OtherTrait>::Assoc == OtherType` /// 3. `::Assoc: OtherTrait` /// /// Replace the span of the cause with the span of the associated item: @@ -292,6 +292,9 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( } // Form 2: A projection obligation for an associated item failed to be met. + // We overwrite the span from above to ensure that a bound like + // `Self::Assoc1: Trait` gets the same + // span for both obligations that it is lowered to. if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) { cause.span = impl_item_span; } diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs index 00a9df35b002d..97dfec80e3167 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.rs +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -33,4 +33,28 @@ impl BoundOnGat for u8 { fn trivial_bound() where (): Sub {} //~^ ERROR the trait bound `(): Sub` is not satisfied +// The following is an edge case where the unsatisfied projection predicate +// `<::Assoc1<()> as SuperGeneric>::Assoc == ::Assoc2` +// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied +// super projection, the error's span must be equal to the span of the unsatisfied trait error. +trait SuperGeneric { + type Assoc; +} +trait SubGeneric: SuperGeneric {} +trait MultiAssoc +where + Self::Assoc1<()>: SubGeneric +{ + type Assoc1; + type Assoc2; +} +impl SuperGeneric for () { + type Assoc = u8; +} +impl MultiAssoc for u8 { + type Assoc1 = (); + //~^ ERROR the trait bound `(): SubGeneric` is not satisfied + type Assoc2 = u16; +} + fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr index 0ce0b66cbf909..47535776348b9 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -80,6 +80,26 @@ LL | trait Sub: Super {} = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable -error: aborting due to 5 previous errors +error[E0277]: the trait bound `(): SubGeneric` is not satisfied + --> $DIR/super-assoc-mismatch.rs:55:22 + | +LL | type Assoc1 = (); + | ^^ the trait `SubGeneric` is not implemented for `()`, which is required by `::Assoc1<()>: SubGeneric<::Assoc2>` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:43:1 + | +LL | trait SubGeneric: SuperGeneric {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `MultiAssoc` + --> $DIR/super-assoc-mismatch.rs:46:23 + | +LL | trait MultiAssoc + | ---------- required by a bound in this trait +LL | where +LL | Self::Assoc1<()>: SubGeneric + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. From db48b934544705498dcd3e00527138b48feff3d6 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 7 Mar 2024 13:20:56 +0100 Subject: [PATCH 6/6] improve debug logging --- .../src/infer/relate/higher_ranked.rs | 2 +- .../traits/error_reporting/type_err_ctxt_ext.rs | 17 +++-------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index f30e366c19850..cc0f00254ffd8 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -77,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> { // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. let value = self.enter_forall_and_leak_universe(forall); - debug!("?value"); + debug!(?value); f(value) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index c2059230bfcaa..5346d2dbd6239 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1419,6 +1419,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. + #[instrument(level = "debug", skip(self), ret)] fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { if cond == error { return true; @@ -1428,25 +1429,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond)) .filter_map(|implied| implied.to_opt_poly_trait_pred()) - .any(|implied| { - let is_implied = self.can_match_trait(error, implied); - if is_implied { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); - } - is_implied - }) + .any(|implied| self.can_match_trait(error, implied)) }) } else if let Some(error) = error.to_opt_poly_projection_pred() { self.enter_forall(error, |error| { elaborate(self.tcx, std::iter::once(cond)) .filter_map(|implied| implied.to_opt_poly_projection_pred()) - .any(|implied| { - let is_implied = self.can_match_projection(error, implied); - if is_implied { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implied); - } - is_implied - }) + .any(|implied| self.can_match_projection(error, implied)) }) } else { false