From fcc49d262f20703a0e894bcd7713b06d785474d6 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Fri, 14 Aug 2026 16:18:15 +0600 Subject: [PATCH 1/2] suppress projection errors already covered by a trait error under the next solver a closure whose signature doesnt match emitted two errors at the same span. the trait goal `C: FnMut(&i32)` failed, and the `>::Output == bool` projection goal resting on it failed out of that same unification. the old solver collapses both into a single `type mismatch in closure arguments`, so the projection error was noise. suppress a projection error when another error at the same span is a trait goal it rests on. ambiguity errors are exempt, they get merged into one diagnostic whose notes list every constraint the annotation has to satisfy, so their projections still say something the trait error doesnt. --- .../traits/fulfillment_errors.rs | 32 ++++++++++++++++ .../src/error_reporting/traits/mod.rs | 20 +++++++++- ...rg-type-mismatch-issue-45727.current.fixed | 2 - ...g-type-mismatch-issue-45727.current.stderr | 2 +- ...-arg-type-mismatch-issue-45727.next.stderr | 37 +++---------------- .../closure-arg-type-mismatch-issue-45727.rs | 2 - .../const-host-effect-hrtb-no-ice.rs | 1 - .../const-host-effect-hrtb-no-ice.stderr | 17 +-------- .../iterator-item-suggest-no-ice.rs | 1 - .../iterator-item-suggest-no-ice.stderr | 31 ++-------------- 10 files changed, 62 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1897ed8fc84eb..648e190032213 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1593,6 +1593,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } + /// Whether `error`, a projection goal, only failed because the trait goal it rests on + /// did: `::Assoc == U` cannot hold when `T: Trait` doesn't, so an error on + /// the latter says everything the former would. + pub(super) fn trait_error_implies_projection_error( + &self, + cond: Goal<'tcx, ty::Predicate<'tcx>>, + error: Goal<'tcx, ty::Predicate<'tcx>>, + ) -> bool { + if cond.param_env != error.param_env { + return false; + } + let Some(error) = error.predicate.as_projection_clause() else { + return false; + }; + + self.enter_forall(error, |error| { + error.projection_term.kind.is_trait_projection() + && elaborate(self.tcx, std::iter::once(cond.predicate)) + .filter_map(|implied| implied.as_trait_clause()) + .any(|implied| { + self.can_match_trait( + cond.param_env, + ty::TraitPredicate { + trait_ref: error.projection_term.trait_ref(self.tcx), + polarity: ty::PredicatePolarity::Positive, + }, + implied, + ) + }) + }) + } + #[instrument(level = "debug", skip_all)] pub(super) fn report_projection_error( &self, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 8bf5814b9fe13..bd272dee3b3ab 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -224,6 +224,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // We do this in 2 passes because we want to display errors in order, though // maybe it *is* better to sort errors by span or something. let mut is_suppressed = vec![false; errors.len()]; + // A failing trait goal also fails every projection goal resting on it. Ambiguity + // errors are exempt: they get merged into a single diagnostic whose notes list all + // the constraints the annotation has to satisfy, so their projections still say + // something the trait error doesn't. + let covered_by_trait_error = + |cond: &ErrorDescriptor<'tcx>, error: &ErrorDescriptor<'tcx>| { + let is_definite = |error: &ErrorDescriptor<'tcx>| { + error.index.is_some_and(|index| { + !matches!(errors[index].code, FulfillmentErrorCode::Ambiguity { .. }) + }) + }; + is_definite(cond) + && is_definite(error) + && self.trait_error_implies_projection_error(cond.goal, error.goal) + }; for (_, error_set) in error_map.iter() { // We want to suppress "duplicate" errors with the same span. for error in error_set { @@ -239,9 +254,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { continue; } - if self.error_implies(error2.goal, error.goal) + if (self.error_implies(error2.goal, error.goal) && !(error2.index >= error.index - && self.error_implies(error.goal, error2.goal)) + && self.error_implies(error.goal, error2.goal))) + || covered_by_trait_error(error2, error) { info!("skipping {:?} (implied by {:?})", error, error2); is_suppressed[index] = true; diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed index b1158e1cbffa7..1ff52c9e5a38a 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed @@ -6,9 +6,7 @@ fn main() { let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found - //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found - //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr index a6ba644f3a44a..c35d70a635cbd 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr @@ -16,7 +16,7 @@ LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0); | + error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); | ^^^^ ----------- found signature defined here diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index 2c51d1e9aec4d..baeff76e1ffe2 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -12,45 +12,20 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0271]: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:38 - | -LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); - | ---- -------- ^^^^^^^^^^^^^^^ types differ - | | | - | | this closure - | required by a bound introduced by this call - | -note: required by a bound in `find` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - -error[E0277]: expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:29 +error[E0277]: expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:10:29: 10:40}` + = help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` = note: expected a closure with signature `for<'a> fn(&'a {integer})` found a closure with signature `fn(&&&i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0271]: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:10:41 - | -LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ---- ----------- ^^^^^^^^^^^^^^^ types differ - | | | - | | this closure - | required by a bound introduced by this call - | -note: required by a bound in `find` - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - -error: aborting due to 4 previous errors +error: aborting due to 2 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`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index 09f7af7c0253e..0a0abfafc45a2 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -6,9 +6,7 @@ fn main() { let _ = (-10..=10).find(|x: i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found - //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:6:29} as FnOnce<(&{integer},)>>::Output == bool` let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found - //[next]~| ERROR: type mismatch resolving `<{closure@closure-arg-type-mismatch-issue-45727.rs:10:29} as FnOnce<(&{integer},)>>::Output == bool` } diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs index a0d1db3ff02b3..b53d30e5f5c9c 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs @@ -8,7 +8,6 @@ const fn with_positive [const] Fn(&'a ())>() {} const _: () = { with_positive::<()>(); //~^ ERROR expected an `Fn(&'a ())` closure, found `()` - //~| ERROR type mismatch resolving `<() as FnOnce<(&(),)>>::Output == ()` }; fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr index 7b98ba618a727..3b1126e253abd 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr @@ -11,19 +11,6 @@ note: required by a bound in `with_positive` LL | const fn with_positive [const] Fn(&'a ())>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_positive` -error[E0271]: type mismatch resolving `<() as FnOnce<(&(),)>>::Output == ()` - --> $DIR/const-host-effect-hrtb-no-ice.rs:9:21 - | -LL | with_positive::<()>(); - | ^^ types differ - | -note: required by a bound in `with_positive` - --> $DIR/const-host-effect-hrtb-no-ice.rs:6:43 - | -LL | const fn with_positive [const] Fn(&'a ())>() {} - | ^^^^^^^^^^ required by this bound in `with_positive` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -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`. diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs index 89a37d8c75a31..1d17909e26a92 100644 --- a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.rs @@ -15,7 +15,6 @@ trait FooMut { //~^ ERROR: cannot find value `_I` in this scope self.bar(collection); //~^ ERROR: `&'b _` is not an iterator - //~| ERROR: type mismatch resolving `<&_ as Iterator>::Item == &()` } } diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr index 0bd604d03fdf2..7f160b1b7e951 100644 --- a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr @@ -40,32 +40,7 @@ LL | where LL | for<'b> &'b I: Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FooMut::bar` -error[E0271]: type mismatch resolving `<&_ as Iterator>::Item == &()` - --> $DIR/iterator-item-suggest-no-ice.rs:16:18 - | -LL | self.bar(collection); - | --- ^^^^^^^^^^ types differ - | | - | required by a bound introduced by this call - | -note: the method call chain might not have had the expected associated types - --> $DIR/iterator-item-suggest-no-ice.rs:14:35 - | -LL | let collection = vec![_I].iter().map(|x| ()); - | -------- ^^^^^^ ----------- `Iterator::Item` remains `<{type error} as Iterator>::Item` here - | | | - | | `Iterator::Item` is `<{type error} as Iterator>::Item` here - | this expression has type `Vec<{type error}>` -note: required by a bound in `FooMut::bar` - --> $DIR/iterator-item-suggest-no-ice.rs:7:33 - | -LL | fn bar(&self, _: I) - | --- required by a bound in this associated function -LL | where -LL | for<'b> &'b I: Iterator; - | ^^^^^^^^^^^^^ required by this bound in `FooMut::bar` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0271, E0277, E0425, E0428. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0277, E0425, E0428. +For more information about an error, try `rustc --explain E0277`. From c67d6dfe850fb9c8e8765c422359e14a8c1652fa Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Tue, 18 Aug 2026 21:36:42 +0600 Subject: [PATCH 2/2] only suppress a projection error when its own trait goal fails elaborating `cond` reaches supertraits, so a projection resting on a supertrait got suppressed even when that supertrait holds and the projection had failed for its own reasons. that dropped a real error, on the old solver too. require the trait goal the projection rests on to be unproven before treating the trait error as covering it. --- .../traits/fulfillment_errors.rs | 33 +++++++----- ...ndependent-projection-error.current.stderr | 53 +++++++++++++++++++ ...s-independent-projection-error.next.stderr | 53 +++++++++++++++++++ ...t-suppress-independent-projection-error.rs | 31 +++++++++++ 4 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr create mode 100644 tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr create mode 100644 tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.rs diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 648e190032213..6293c85f595d8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1609,19 +1609,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; self.enter_forall(error, |error| { - error.projection_term.kind.is_trait_projection() - && elaborate(self.tcx, std::iter::once(cond.predicate)) - .filter_map(|implied| implied.as_trait_clause()) - .any(|implied| { - self.can_match_trait( - cond.param_env, - ty::TraitPredicate { - trait_ref: error.projection_term.trait_ref(self.tcx), - polarity: ty::PredicatePolarity::Positive, - }, - implied, - ) - }) + if !error.projection_term.kind.is_trait_projection() { + return false; + } + let trait_pred = ty::TraitPredicate { + trait_ref: error.projection_term.trait_ref(self.tcx), + polarity: ty::PredicatePolarity::Positive, + }; + // Elaborating is what pairs a failing `C: FnMut(..)` with the + // `>::Output` projection resting on it. A supertrait can hold + // while `cond` fails though, so the projection is only covered if its own trait + // goal is unproven too, otherwise it failed for its own reasons. + elaborate(self.tcx, std::iter::once(cond.predicate)) + .filter_map(|implied| implied.as_trait_clause()) + .any(|implied| self.can_match_trait(cond.param_env, trait_pred, implied)) + && !self.predicate_must_hold_modulo_regions(&Obligation::new( + self.tcx, + ObligationCause::dummy(), + cond.param_env, + trait_pred, + )) }) } diff --git a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr new file mode 100644 index 0000000000000..546a069bb93ab --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `S: Sub` is not satisfied + --> $DIR/dont-suppress-independent-projection-error.rs:28:7 + | +LL | f(S); + | - ^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `Sub` is not implemented for `S` + --> $DIR/dont-suppress-independent-projection-error.rs:14:1 + | +LL | struct S; + | ^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/dont-suppress-independent-projection-error.rs:12:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `f` + --> $DIR/dont-suppress-independent-projection-error.rs:22:8 + | +LL | fn f(_: T) + | - required by a bound in this function +LL | where +LL | T: Sub, + | ^^^ required by this bound in `f` + +error[E0271]: type mismatch resolving `::Assoc == u32` + --> $DIR/dont-suppress-independent-projection-error.rs:28:7 + | +LL | f(S); + | - ^ type mismatch resolving `::Assoc == u32` + | | + | required by a bound introduced by this call + | +note: expected this to be `u32` + --> $DIR/dont-suppress-independent-projection-error.rs:17:18 + | +LL | type Assoc = u8; + | ^^ +note: required by a bound in `f` + --> $DIR/dont-suppress-independent-projection-error.rs:23:14 + | +LL | fn f(_: T) + | - required by a bound in this function +... +LL | T: Super, + | ^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr new file mode 100644 index 0000000000000..546a069bb93ab --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `S: Sub` is not satisfied + --> $DIR/dont-suppress-independent-projection-error.rs:28:7 + | +LL | f(S); + | - ^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `Sub` is not implemented for `S` + --> $DIR/dont-suppress-independent-projection-error.rs:14:1 + | +LL | struct S; + | ^^^^^^^^ +help: this trait has no implementations, consider adding one + --> $DIR/dont-suppress-independent-projection-error.rs:12:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `f` + --> $DIR/dont-suppress-independent-projection-error.rs:22:8 + | +LL | fn f(_: T) + | - required by a bound in this function +LL | where +LL | T: Sub, + | ^^^ required by this bound in `f` + +error[E0271]: type mismatch resolving `::Assoc == u32` + --> $DIR/dont-suppress-independent-projection-error.rs:28:7 + | +LL | f(S); + | - ^ type mismatch resolving `::Assoc == u32` + | | + | required by a bound introduced by this call + | +note: expected this to be `u32` + --> $DIR/dont-suppress-independent-projection-error.rs:17:18 + | +LL | type Assoc = u8; + | ^^ +note: required by a bound in `f` + --> $DIR/dont-suppress-independent-projection-error.rs:23:14 + | +LL | fn f(_: T) + | - required by a bound in this function +... +LL | T: Super, + | ^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.rs b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.rs new file mode 100644 index 0000000000000..2209597254da4 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.rs @@ -0,0 +1,31 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// A projection error is only redundant when the trait goal it rests on failed too. +// Here `S: Super` holds, so `::Assoc == u32` failed on its own and has to +// be reported even though the `S: Sub` error at the same span elaborates to `S: Super`. + +trait Super { + type Assoc; +} +trait Sub: Super {} + +struct S; + +impl Super for S { + type Assoc = u8; +} + +fn f(_: T) +where + T: Sub, + T: Super, +{ +} + +fn main() { + f(S); + //~^ ERROR the trait bound `S: Sub` is not satisfied + //~| ERROR type mismatch resolving `::Assoc == u32` +}