diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 4c34bf88c7f96..3ad6b68d1299b 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -273,6 +273,8 @@ pub enum GoalSource { /// they are from an impl where-clause. This is necessary due to /// backwards compatability, cc trait-system-refactor-initiatitive#70. ImplWhereBound, + /// Instantiating a higher-ranked goal and re-proving it. + InstantiateHigherRanked, } /// Possible ways the given goal can be proven. diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 2d73be387fdcd..11aa0e10931cb 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -127,6 +127,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { let source = match source { GoalSource::Misc => "misc", GoalSource::ImplWhereBound => "impl where-bound", + GoalSource::InstantiateHigherRanked => "higher-ranked goal", }; writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")? } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 35a3ac03a94aa..bae1c6b60115e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -454,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } else { self.infcx.enter_forall(kind, |kind| { let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::ImplWhereBound, goal); + self.add_goal(GoalSource::InstantiateHigherRanked, goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index d4fde60fd4a72..796222129f180 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -7,10 +7,10 @@ use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, - PredicateObligation, SelectionError, TraitEngine, + ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, TyCtxt}; use super::eval_ctxt::GenerateProofTree; use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; @@ -219,14 +219,14 @@ fn fulfillment_error_for_no_solution<'tcx>( } ty::PredicateKind::Subtype(pred) => { let (a, b) = infcx.enter_forall_and_leak_universe( - root_obligation.predicate.kind().rebind((pred.a, pred.b)), + obligation.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(true, a, b); FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found)) } ty::PredicateKind::Coerce(pred) => { let (a, b) = infcx.enter_forall_and_leak_universe( - root_obligation.predicate.kind().rebind((pred.a, pred.b)), + obligation.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found)) @@ -272,6 +272,20 @@ fn fulfillment_error_for_stalled<'tcx>( } } +fn find_best_leaf_obligation<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, +) -> PredicateObligation<'tcx> { + let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + infcx + .visit_proof_tree( + obligation.clone().into(), + &mut BestObligation { obligation: obligation.clone() }, + ) + .break_value() + .unwrap_or(obligation) +} + struct BestObligation<'tcx> { obligation: PredicateObligation<'tcx>, } @@ -279,10 +293,9 @@ struct BestObligation<'tcx> { impl<'tcx> BestObligation<'tcx> { fn with_derived_obligation( &mut self, - derive_obligation: impl FnOnce(&mut Self) -> PredicateObligation<'tcx>, + derived_obligation: PredicateObligation<'tcx>, and_then: impl FnOnce(&mut Self) -> >::Result, ) -> >::Result { - let derived_obligation = derive_obligation(self); let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); let res = and_then(self); self.obligation = old_obligation; @@ -298,13 +311,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal. + // This most likely means that the goal just didn't unify at all, e.g. a param + // candidate with an alias in it. let candidates = goal.candidates(); - // FIXME: Throw out candidates that have no failing WC and >1 failing misc goal. - - // HACK: - if self.obligation.recursion_depth > 3 { - return ControlFlow::Break(self.obligation.clone()); - } let [candidate] = candidates.as_slice() else { return ControlFlow::Break(self.obligation.clone()); @@ -320,80 +330,71 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { let tcx = goal.infcx().tcx; let mut impl_where_bound_count = 0; for nested_goal in candidate.instantiate_nested_goals(self.span()) { - if matches!(nested_goal.source(), GoalSource::ImplWhereBound) { - impl_where_bound_count += 1; - } else { - continue; + let obligation; + match nested_goal.source() { + GoalSource::Misc => { + continue; + } + GoalSource::ImplWhereBound => { + obligation = Obligation { + cause: derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + ), + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + impl_where_bound_count += 1; + } + GoalSource::InstantiateHigherRanked => { + obligation = self.obligation.clone(); + } } // Skip nested goals that hold. + //FIXME: We should change the max allowed certainty based on if we're + // visiting an ambiguity or error obligation. if matches!(nested_goal.result(), Ok(Certainty::Yes)) { continue; } - self.with_derived_obligation( - |self_| { - let mut cause = self_.obligation.cause.clone(); - cause = match candidate.kind() { - ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } => { - let idx = impl_where_bound_count - 1; - if let Some((_, span)) = tcx - .predicates_of(impl_def_id) - .instantiate_identity(tcx) - .iter() - .nth(idx) - { - cause.derived_cause(parent_trait_pred, |derived| { - traits::ImplDerivedObligation(Box::new( - traits::ImplDerivedObligationCause { - derived, - impl_or_alias_def_id: impl_def_id, - impl_def_predicate_index: Some(idx), - span, - }, - )) - }) - } else { - cause - } - } - ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(..), - result: _, - } => { - cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation) - } - _ => cause, - }; - - Obligation { - cause, - param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, - recursion_depth: self_.obligation.recursion_depth + 1, - } - }, - |self_| self_.visit_goal(&nested_goal), - )?; + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; } ControlFlow::Break(self.obligation.clone()) } } -fn find_best_leaf_obligation<'tcx>( - infcx: &InferCtxt<'tcx>, - obligation: &PredicateObligation<'tcx>, -) -> PredicateObligation<'tcx> { - let obligation = infcx.resolve_vars_if_possible(obligation.clone()); - infcx - .visit_proof_tree( - obligation.clone().into(), - &mut BestObligation { obligation: obligation.clone() }, - ) - .break_value() - .unwrap_or(obligation) +fn derive_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: ProbeKind<'tcx>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, +) -> ObligationCause<'tcx> { + match candidate_kind { + ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => { + if let Some((_, span)) = + tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) + { + cause = cause.derived_cause(parent_trait_pred, |derived| { + traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause { + derived, + impl_or_alias_def_id: impl_def_id, + impl_def_predicate_index: Some(idx), + span, + })) + }) + } + } + ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => { + cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation); + } + _ => {} + }; + cause } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index de6c2322e8d8d..64a9a836b3dd4 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -128,10 +128,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { /// back their inference constraints. This function modifies /// the state of the `infcx`. pub fn visit_nested_no_probe>(&self, visitor: &mut V) -> V::Result { - if self.goal.depth < visitor.config().max_depth { - for goal in self.instantiate_nested_goals(visitor.span()) { - try_visit!(visitor.visit_goal(&goal)); - } + for goal in self.instantiate_nested_goals(visitor.span()) { + try_visit!(goal.visit_with(visitor)); } V::Result::output() @@ -360,6 +358,14 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { source, } } + + pub(crate) fn visit_with>(&self, visitor: &mut V) -> V::Result { + if self.depth < visitor.config().max_depth { + try_visit!(visitor.visit_goal(self)); + } + + V::Result::output() + } } /// The public API to interact with proof trees. diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index 1c2e445f63ec6..6e68646fbe4f4 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -6,7 +6,7 @@ LL | impl Trait for W {} LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W>>>>>>>>>>>>>>>>>>>>>` | - = note: overflow evaluating the requirement `W>>>>>>>>>>>>>: TwoW` + = note: overflow evaluating the requirement `W>>>: TwoW` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`coherence_fulfill_overflow`) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr index 0fe594bbb2daa..86c71ad92ff8a 100644 --- a/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr +++ b/tests/ui/traits/next-solver/cycles/double-cycle-inductive-coinductive.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): Trait` +error[E0275]: overflow evaluating the requirement `(): Inductive` --> $DIR/double-cycle-inductive-coinductive.rs:32:19 | LL | impls_trait::<()>(); | ^^ | -note: required for `()` to implement `Inductive` - --> $DIR/double-cycle-inductive-coinductive.rs:12:16 - | -LL | impl Inductive for T {} - | ----- ^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `Trait` --> $DIR/double-cycle-inductive-coinductive.rs:9:34 | @@ -18,7 +11,14 @@ LL | impl Trait for T {} | --------- ^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: 2 redundant requirements hidden +note: required for `()` to implement `Inductive` + --> $DIR/double-cycle-inductive-coinductive.rs:12:16 + | +LL | impl Inductive for T {} + | ----- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden = note: required for `()` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/double-cycle-inductive-coinductive.rs:17:19 @@ -26,19 +26,12 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error[E0275]: overflow evaluating the requirement `(): TraitRev` +error[E0275]: overflow evaluating the requirement `(): CoinductiveRev` --> $DIR/double-cycle-inductive-coinductive.rs:35:23 | LL | impls_trait_rev::<()>(); | ^^ | -note: required for `()` to implement `CoinductiveRev` - --> $DIR/double-cycle-inductive-coinductive.rs:27:19 - | -LL | impl CoinductiveRev for T {} - | -------- ^^^^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `TraitRev` --> $DIR/double-cycle-inductive-coinductive.rs:21:40 | @@ -46,7 +39,14 @@ LL | impl TraitRev for T {} | -------------- ^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: 2 redundant requirements hidden +note: required for `()` to implement `CoinductiveRev` + --> $DIR/double-cycle-inductive-coinductive.rs:27:19 + | +LL | impl CoinductiveRev for T {} + | -------- ^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden = note: required for `()` to implement `TraitRev` note: required by a bound in `impls_trait_rev` --> $DIR/double-cycle-inductive-coinductive.rs:29:23 diff --git a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr index 6211e08de703f..ea46c0fea97b8 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr @@ -1,10 +1,10 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `W>: Trait` --> $DIR/inductive-fixpoint-hang.rs:31:19 | LL | impls_trait::>(); | ^^^^ | -note: required for `W>` to implement `Trait` +note: required for `W>>` to implement `Trait` --> $DIR/inductive-fixpoint-hang.rs:22:17 | LL | impl Trait for W> @@ -12,8 +12,8 @@ LL | impl Trait for W> LL | where LL | W: Trait, | ----- unsatisfied trait bound introduced here - = note: 3 redundant requirements hidden - = note: required for `W>>>>` to implement `Trait` + = note: 8 redundant requirements hidden + = note: required for `W>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/inductive-fixpoint-hang.rs:28:19 | diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs index c3a3555f5ade9..9d0ea51b1b25e 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.rs @@ -39,8 +39,8 @@ fn impls_ar() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): A` + //~^ ERROR overflow evaluating the requirement `(): B` impls_ar::<()>(); - //~^ ERROR overflow evaluating the requirement `(): CR` + //~^ ERROR overflow evaluating the requirement `(): AR` } diff --git a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr index 75f82e998c752..fe02d3c407cab 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-not-on-stack.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): B` --> $DIR/inductive-not-on-stack.rs:41:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `B` - --> $DIR/inductive-not-on-stack.rs:22:12 - | -LL | impl B for T {} - | - ^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `A` --> $DIR/inductive-not-on-stack.rs:21:16 | @@ -18,7 +11,14 @@ LL | impl A for T {} | - ^ ^ | | | unsatisfied trait bound introduced here - = note: 2 redundant requirements hidden +note: required for `()` to implement `B` + --> $DIR/inductive-not-on-stack.rs:22:12 + | +LL | impl B for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here + = note: 7 redundant requirements hidden = note: required for `()` to implement `A` note: required by a bound in `impls_a` --> $DIR/inductive-not-on-stack.rs:25:15 @@ -26,19 +26,12 @@ note: required by a bound in `impls_a` LL | fn impls_a() {} | ^ required by this bound in `impls_a` -error[E0275]: overflow evaluating the requirement `(): CR` +error[E0275]: overflow evaluating the requirement `(): AR` --> $DIR/inductive-not-on-stack.rs:44:16 | LL | impls_ar::<()>(); | ^^ | -note: required for `()` to implement `AR` - --> $DIR/inductive-not-on-stack.rs:34:18 - | -LL | impl AR for T {} - | -- ^^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `BR` --> $DIR/inductive-not-on-stack.rs:35:13 | @@ -53,7 +46,14 @@ LL | impl CR for T {} | -- ^^ ^ | | | unsatisfied trait bound introduced here - = note: 1 redundant requirement hidden +note: required for `()` to implement `AR` + --> $DIR/inductive-not-on-stack.rs:34:18 + | +LL | impl AR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 6 redundant requirements hidden = note: required for `()` to implement `AR` note: required by a bound in `impls_ar` --> $DIR/inductive-not-on-stack.rs:38:16 diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs index 170446363cac8..b90a354be1b61 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs @@ -35,5 +35,5 @@ fn impls_a() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): C` + //~^ ERROR overflow evaluating the requirement `(): CInd` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr index f785a9abc2370..03e61dbf99c22 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): C` +error[E0275]: overflow evaluating the requirement `(): CInd` --> $DIR/mixed-cycles-1.rs:37:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `CInd` - --> $DIR/mixed-cycles-1.rs:28:21 - | -LL | impl CInd for T {} - | - ^^^^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `B` --> $DIR/mixed-cycles-1.rs:31:28 | @@ -18,6 +11,22 @@ LL | impl B for T {} | ---- ^ ^ | | | unsatisfied trait bound introduced here +note: required for `()` to implement `C` + --> $DIR/mixed-cycles-1.rs:32:25 + | +LL | impl C for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `CInd` + --> $DIR/mixed-cycles-1.rs:28:21 + | +LL | impl CInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 4 redundant requirements hidden + = note: required for `()` to implement `B` note: required for `()` to implement `BInd` --> $DIR/mixed-cycles-1.rs:23:21 | diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs index 3f9c290f70697..a3ffcaafb3758 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs @@ -28,5 +28,5 @@ fn impls_a() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): B` + //~^ ERROR overflow evaluating the requirement `(): BInd` } diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr index c4071f2f56ab3..892426abe82e6 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr @@ -1,16 +1,9 @@ -error[E0275]: overflow evaluating the requirement `(): B` +error[E0275]: overflow evaluating the requirement `(): BInd` --> $DIR/mixed-cycles-2.rs:30:15 | LL | impls_a::<()>(); | ^^ | -note: required for `()` to implement `BInd` - --> $DIR/mixed-cycles-2.rs:22:21 - | -LL | impl BInd for T {} - | - ^^^^ ^ - | | - | unsatisfied trait bound introduced here note: required for `()` to implement `B` --> $DIR/mixed-cycles-2.rs:25:24 | @@ -18,7 +11,14 @@ LL | impl B for T {} | ---- ^ ^ | | | unsatisfied trait bound introduced here - = note: 1 redundant requirement hidden +note: required for `()` to implement `BInd` + --> $DIR/mixed-cycles-2.rs:22:21 + | +LL | impl BInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 6 redundant requirements hidden = note: required for `()` to implement `BInd` note: required for `()` to implement `A` --> $DIR/mixed-cycles-2.rs:24:28 diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr index 1ef86abcebe15..9e467721e83e3 100644 --- a/tests/ui/traits/next-solver/overflow/global-cache.stderr +++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr @@ -5,14 +5,14 @@ LL | impls_trait::>>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "18"]` attribute to your crate (`global_cache`) -note: required for `Inc>>>>>>>>>>>>` to implement `Trait` +note: required for `Inc>>>>>>>>>>` to implement `Trait` --> $DIR/global-cache.rs:12:16 | LL | impl Trait for Inc {} | ----- ^^^^^ ^^^^^^ | | | unsatisfied trait bound introduced here - = note: 3 redundant requirements hidden + = note: 5 redundant requirements hidden = note: required for `Inc>>>>>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/global-cache.rs:15:19