From 837bde11a2e1796910df8a6196f56c58fac6319c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 May 2024 16:03:08 -0400 Subject: [PATCH 1/5] Record certainty before evaluating nesteds, so we make candidates --- .../rustc_trait_selection/src/solve/eval_ctxt/canonical.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 6722abd709c..d6bf2b596ef 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -90,6 +90,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, certainty: Certainty, ) -> QueryResult<'tcx> { + self.inspect.make_canonical_response(certainty); + let goals_certainty = self.try_evaluate_added_goals()?; assert_eq!( self.tainted, @@ -98,8 +100,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { previous call to `try_evaluate_added_goals!`" ); - self.inspect.make_canonical_response(certainty); - // When normalizing, we've replaced the expected term with an unconstrained // inference variable. This means that we dropped information which could // have been important. We handle this by instead returning the nested goals From 6e3808e27407c967762f56a2ddffe2602a3079a3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Apr 2024 18:41:08 -0400 Subject: [PATCH 2/5] Store goal source in InspectGoal --- .../src/solve/inspect/analyse.rs | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 7c6dd4d3feb..de6c2322e8d 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -42,6 +42,7 @@ pub struct InspectGoal<'a, 'tcx> { result: Result, evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>, normalizes_to_term_hack: Option>, + source: GoalSource, } /// The expected term of a `NormalizesTo` goal gets replaced @@ -92,7 +93,7 @@ impl<'tcx> NormalizesToTermHack<'tcx> { pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, kind: inspect::ProbeKind<'tcx>, - nested_goals: Vec>>>, + nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>, final_state: inspect::CanonicalState<'tcx, ()>, result: QueryResult<'tcx>, shallow_certainty: Certainty, @@ -145,13 +146,16 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let instantiated_goals: Vec<_> = self .nested_goals .iter() - .map(|goal| { - canonical::instantiate_canonical_state( - infcx, - span, - param_env, - &mut orig_values, - *goal, + .map(|(source, goal)| { + ( + *source, + canonical::instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + *goal, + ), ) }) .collect(); @@ -173,7 +177,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { instantiated_goals .into_iter() - .map(|goal| match goal.predicate.kind().no_bound_vars() { + .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { let unconstrained_term = match term.unpack() { ty::TermKind::Ty(_) => infcx @@ -197,6 +201,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.goal.depth + 1, proof_tree.unwrap(), Some(NormalizesToTermHack { term, unconstrained_term }), + source, ) } _ => InspectGoal::new( @@ -204,6 +209,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.goal.depth + 1, infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(), None, + source, ), }) .collect() @@ -229,16 +235,23 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { self.result } + pub fn source(&self) -> GoalSource { + self.source + } + fn candidates_recur( &'a self, candidates: &mut Vec>, - nested_goals: &mut Vec>>>, + nested_goals: &mut Vec<( + GoalSource, + inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>, + )>, probe: &inspect::Probe<'tcx>, ) { let mut shallow_certainty = None; for step in &probe.steps { match step { - &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal), + &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::NestedProbe(ref probe) => { // Nested probes have to prove goals added in their parent // but do not leak them, so we truncate the added goals @@ -321,6 +334,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { depth: usize, root: inspect::GoalEvaluation<'tcx>, normalizes_to_term_hack: Option>, + source: GoalSource, ) -> Self { let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root; let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() }; @@ -343,6 +357,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { result, evaluation_kind: evaluation.kind, normalizes_to_term_hack, + source, } } } @@ -369,6 +384,6 @@ impl<'tcx> InferCtxt<'tcx> { ) -> V::Result { let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None)) + visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc)) } } From 382d0f73adbf1cece11863b850059931c0d9c632 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 May 2024 15:58:51 -0400 Subject: [PATCH 3/5] Record more kinds of things as impl where bounds --- .../src/solve/assembly/mod.rs | 15 +++++++-------- .../src/solve/normalizes_to/mod.rs | 5 +++-- .../src/solve/trait_goals.rs | 5 +++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 280975f63bd..f2ca42a0be9 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -58,15 +58,15 @@ pub(super) trait GoalKind<'tcx>: /// goal by equating it with the assumption. fn probe_and_consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + parent_source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, - requirements: impl IntoIterator>>, + requirements: impl IntoIterator>)>, ) -> Result, NoSolution> { - Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { - // FIXME(-Znext-solver=coinductive): check whether this should be - // `GoalSource::ImplWhereBound` for any caller. - ecx.add_goals(GoalSource::Misc, requirements); + Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| { + for (nested_source, goal) in requirements { + ecx.add_goal(nested_source, goal); + } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -85,9 +85,8 @@ pub(super) trait GoalKind<'tcx>: let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else { bug!("expected object type in `probe_and_consider_object_bound_candidate`"); }; - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? ecx.add_goals( - GoalSource::Misc, + GoalSource::ImplWhereBound, structural_traits::predicates_for_object_candidate( ecx, goal.param_env, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index dab87fffe46..f886c588650 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -389,7 +389,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)], + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], ) } @@ -473,7 +473,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index c8cb14abb55..d2b893d6383 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -321,7 +321,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)], + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], ) } @@ -367,7 +367,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } From 3e03b1b19081ad50de2af5635e9fd9fb9f3489bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 May 2024 16:03:26 -0400 Subject: [PATCH 4/5] Use a proof tree visitor to refine the Obligation for error reporting --- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/fulfill.rs | 155 +++++++++++++++++- .../occurs-check/opaques.next.stderr | 2 +- tests/ui/for/issue-20605.next.stderr | 9 +- .../leak-check-in-selection-3.next.stderr | 15 +- .../auto-with-drop_tracking_mir.fail.stderr | 20 ++- .../auto-with-drop_tracking_mir.rs | 2 +- .../builtin-fn-must-return-sized.rs | 2 +- .../builtin-fn-must-return-sized.stderr | 7 +- .../coherence-fulfill-overflow.stderr | 6 +- .../fixpoint-exponential-growth.stderr | 9 +- .../incompleteness-unstable-result.rs | 2 +- .../incompleteness-unstable-result.stderr | 17 +- .../double-cycle-inductive-coinductive.stderr | 32 ++++ .../cycles/inductive-fixpoint-hang.stderr | 10 ++ .../cycles/inductive-not-on-stack.rs | 2 +- .../cycles/inductive-not-on-stack.stderr | 41 ++++- .../next-solver/cycles/mixed-cycles-1.rs | 2 +- .../next-solver/cycles/mixed-cycles-1.stderr | 30 +++- .../next-solver/cycles/mixed-cycles-2.rs | 2 +- .../next-solver/cycles/mixed-cycles-2.stderr | 25 ++- .../param-candidate-shadows-project.rs | 2 +- .../param-candidate-shadows-project.stderr | 20 ++- .../traits/next-solver/more-object-bound.rs | 2 +- .../next-solver/more-object-bound.stderr | 11 +- ...ojection-param-candidates-are-ambiguous.rs | 2 +- ...tion-param-candidates-are-ambiguous.stderr | 13 +- .../ui/traits/next-solver/object-unsafety.rs | 2 +- .../traits/next-solver/object-unsafety.stderr | 11 +- .../overflow/exponential-trait-goals.rs | 2 +- .../overflow/exponential-trait-goals.stderr | 9 +- .../next-solver/overflow/global-cache.stderr | 9 + 32 files changed, 406 insertions(+), 69 deletions(-) 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 1710746ae50..35a3ac03a94 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::Misc, goal); + self.add_goal(GoalSource::ImplWhereBound, 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 3fa409eefff..d4fde60fd4a 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,15 +1,19 @@ use std::mem; +use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::solve::MaybeCause; +use rustc_infer::traits::query::NoSolution; +use rustc_infer::traits::solve::inspect::ProbeKind; +use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, + self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, PredicateObligation, SelectionError, TraitEngine, }; use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use super::eval_ctxt::GenerateProofTree; +use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; /// A trait engine using the new trait solver. @@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .collect(); errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { - root_obligation: obligation.clone(), + obligation: find_best_leaf_obligation(infcx, &obligation), code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - obligation, + root_obligation: obligation, })); errors @@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, + root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { + let obligation = find_best_leaf_obligation(infcx, &root_obligation); + let code = match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { FulfillmentErrorCode::ProjectionError( @@ -213,14 +219,14 @@ fn fulfillment_error_for_no_solution<'tcx>( } ty::PredicateKind::Subtype(pred) => { let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), + root_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( - obligation.predicate.kind().rebind((pred.a, pred.b)), + root_obligation.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); FulfillmentErrorCode::SubtypeError(expected_found, TypeError::Sorts(expected_found)) @@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>( bug!("unexpected goal: {obligation:?}") } }; - FulfillmentError { root_obligation: obligation.clone(), code, obligation } + + FulfillmentError { obligation, code, root_obligation } } fn fulfillment_error_for_stalled<'tcx>( @@ -258,5 +265,135 @@ fn fulfillment_error_for_stalled<'tcx>( } }); - FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation } + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &obligation), + code, + root_obligation: obligation, + } +} + +struct BestObligation<'tcx> { + obligation: PredicateObligation<'tcx>, +} + +impl<'tcx> BestObligation<'tcx> { + fn with_derived_obligation( + &mut self, + derive_obligation: impl FnOnce(&mut Self) -> 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; + res + } +} + +impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { + type Result = ControlFlow>; + + fn span(&self) -> rustc_span::Span { + self.obligation.cause.span + } + + fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + 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()); + }; + + // FIXME: Could we extract a trait ref from a projection here too? + // FIXME: Also, what about considering >1 layer up the stack? May be necessary + // for normalizes-to. + let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + 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; + } + + // Skip nested goals that hold. + 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), + )?; + } + + 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) } diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index a5182eb5d9c..f6c5255a186 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -11,7 +11,7 @@ error[E0282]: type annotations needed --> $DIR/opaques.rs:13:20 | LL | pub fn cast(x: Container, T>) -> Container { - | ^ cannot infer type for struct `Container` + | ^ cannot infer type for associated type `>::Assoc` error: aborting due to 2 previous errors diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index 0669999cb82..6855e17df9a 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -2,9 +2,14 @@ error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:6:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ `dyn Iterator` is not an iterator + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` | - = help: the trait `IntoIterator` is not implemented for `dyn Iterator` + = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied + = note: required for `dyn Iterator` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut *things { *item = 0 } + | ++++ error: the type ` as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:6:17 diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr index 8a8118dea85..5be683cd319 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-3.next.stderr @@ -23,7 +23,20 @@ error[E0283]: type annotations needed LL | impls_indirect_leak::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `impls_indirect_leak` | - = note: cannot satisfy `for<'a> Box<_>: IndirectLeak<'a>` +note: multiple `impl`s satisfying `for<'a> Box<_>: Leak<'a>` found + --> $DIR/leak-check-in-selection-3.rs:9:1 + | +LL | impl Leak<'_> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Leak<'static> for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required for `Box<_>` to implement `for<'a> IndirectLeak<'a>` + --> $DIR/leak-check-in-selection-3.rs:23:23 + | +LL | impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {} + | -------- ^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_indirect_leak` --> $DIR/leak-check-in-selection-3.rs:25:27 | diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr index ac05dfb2d46..562d7ccf9fe 100644 --- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr +++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr @@ -1,18 +1,26 @@ -error[E0277]: `impl Future` cannot be sent between threads safely +error: future cannot be sent between threads safely --> $DIR/auto-with-drop_tracking_mir.rs:25:13 | LL | is_send(foo()); - | ------- ^^^^^ `impl Future` cannot be sent between threads safely - | | - | required by a bound introduced by this call + | ^^^^^ future returned by `foo` is not `Send` | - = help: the trait `Send` is not implemented for `impl Future` + = help: the trait `Sync` is not implemented for `impl Future`, which is required by `impl Future: Send` +note: future is not `Send` as this value is used across an await + --> $DIR/auto-with-drop_tracking_mir.rs:16:11 + | +LL | let x = &NotSync; + | - has type `&NotSync` which is not `Send` +LL | bar().await; + | ^^^^^ await occurs here, with `x` maybe used later note: required by a bound in `is_send` --> $DIR/auto-with-drop_tracking_mir.rs:24:24 | LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` +help: consider dereferencing here + | +LL | is_send(*foo()); + | + error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs index c82c1793119..17741161b31 100644 --- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs +++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.rs @@ -23,5 +23,5 @@ async fn bar() {} fn main() { fn is_send(_: impl Send) {} is_send(foo()); - //[fail]~^ ERROR `impl Future` cannot be sent between threads safely + //[fail]~^ ERROR future cannot be sent between threads safely } diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs index ccb10bab6c1..f8926b24e3f 100644 --- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs +++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs @@ -13,5 +13,5 @@ fn foo, T: Tuple>(f: Option, t: T) { fn main() { foo:: str, _>(None, ()); - //~^ expected a `Fn<_>` closure, found `fn() -> str` + //~^ the size for values of type `str` cannot be known at compilation time } diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr index 08047852f20..b487ceef1d4 100644 --- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr +++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.stderr @@ -1,10 +1,11 @@ -error[E0277]: expected a `Fn<_>` closure, found `fn() -> str` +error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/builtin-fn-must-return-sized.rs:15:11 | LL | foo:: str, _>(None, ()); - | ^^^^^^^^^^^ expected an `Fn<_>` closure, found `fn() -> str` + | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Fn<_>` is not implemented for `fn() -> str` + = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>` + = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` --> $DIR/builtin-fn-must-return-sized.rs:10:11 | 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 57cba790b55..1c2e445f63e 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,12 +1,12 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>` +error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>>` --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl Trait for W {} | ------------------------------------- first implementation here LL | impl Trait for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W>>>>>>>>>>>>>>>>>>>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index 8d7d8cee08a..df25150c21f 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -1,9 +1,16 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `_: Sized` --> $DIR/fixpoint-exponential-growth.rs:33:13 | LL | impls::>(); | ^^^^ | +note: required for `W<(W<_>, W<_>)>` to implement `Trait` + --> $DIR/fixpoint-exponential-growth.rs:23:12 + | +LL | impl Trait for W<(W, W)> + | - ^^^^^ ^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/fixpoint-exponential-growth.rs:30:13 | diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs index 7eea81ce03c..bc9bb6ce2d7 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs @@ -61,7 +61,7 @@ where // entering the cycle from `A` fails, but would work if we were to use the cache // result of `B`. impls_trait::, _, _, _>(); - //~^ ERROR the trait bound `A: Trait<_, _, _>` is not satisfied + //~^ ERROR the trait bound `X: IncompleteGuidance<_, _>` is not satisfied } fn main() { diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr index d4932191791..78116ebba82 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr @@ -1,10 +1,21 @@ -error[E0277]: the trait bound `A: Trait<_, _, _>` is not satisfied +error[E0277]: the trait bound `X: IncompleteGuidance<_, _>` is not satisfied --> $DIR/incompleteness-unstable-result.rs:63:19 | LL | impls_trait::, _, _, _>(); - | ^^^^ the trait `Trait<_, _, _>` is not implemented for `A` + | ^^^^ the trait `IncompleteGuidance<_, _>` is not implemented for `X`, which is required by `A: Trait<_, _, _>` | - = help: the trait `Trait` is implemented for `A` + = help: the following other types implement trait `IncompleteGuidance`: + > + > + > +note: required for `A` to implement `Trait<_, _, u8>` + --> $DIR/incompleteness-unstable-result.rs:32:50 + | +LL | impl Trait for A + | ^^^^^^^^^^^^^^ ^^^^ +LL | where +LL | T: IncompleteGuidance, + | ------------------------ unsatisfied trait bound introduced here note: required by a bound in `impls_trait` --> $DIR/incompleteness-unstable-result.rs:51:28 | 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 7cedb4d36c9..0fe594bbb2d 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 @@ -4,6 +4,22 @@ error[E0275]: overflow evaluating the requirement `(): Trait` 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 + | +LL | impl Trait for T {} + | --------- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 2 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 | @@ -16,6 +32,22 @@ error[E0275]: overflow evaluating the requirement `(): TraitRev` 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 + | +LL | impl TraitRev for T {} + | -------------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 2 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 a2a5c028cf8..6211e08de70 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-fixpoint-hang.stderr @@ -4,6 +4,16 @@ error[E0275]: overflow evaluating the requirement `W<_>: Trait` LL | impls_trait::>(); | ^^^^ | +note: required for `W>` to implement `Trait` + --> $DIR/inductive-fixpoint-hang.rs:22:17 + | +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: 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 78683372580..c3a3555f5ad 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 @@ -42,5 +42,5 @@ fn main() { //~^ ERROR overflow evaluating the requirement `(): A` impls_ar::<()>(); - //~^ ERROR overflow evaluating the requirement `(): AR` + //~^ ERROR overflow evaluating the requirement `(): CR` } 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 e9cc6bc6c81..75f82e998c7 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 @@ -4,18 +4,57 @@ error[E0275]: overflow evaluating the requirement `(): A` 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 + | +LL | impl A for T {} + | - ^ ^ + | | + | unsatisfied trait bound introduced here + = note: 2 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 | LL | fn impls_a() {} | ^ required by this bound in `impls_a` -error[E0275]: overflow evaluating the requirement `(): AR` +error[E0275]: overflow evaluating the requirement `(): CR` --> $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 + | +LL | impl BR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `CR` + --> $DIR/inductive-not-on-stack.rs:36:13 + | +LL | impl CR for T {} + | -- ^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement 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 6d75d241864..170446363ca 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 `(): A` + //~^ ERROR overflow evaluating the requirement `(): C` } 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 17544eb1da5..f785a9abc23 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr @@ -1,9 +1,37 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): C` --> $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 + | +LL | impl B for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `BInd` + --> $DIR/mixed-cycles-1.rs:23:21 + | +LL | impl BInd for T {} + | - ^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `()` to implement `A` + --> $DIR/mixed-cycles-1.rs:30:28 + | +LL | impl A for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-1.rs:34:15 | 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 c939a6e5ef2..3f9c290f706 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 `(): A` + //~^ ERROR overflow evaluating the requirement `(): B` } 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 a9be1016c74..c4071f2f56a 100644 --- a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr +++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr @@ -1,9 +1,32 @@ -error[E0275]: overflow evaluating the requirement `(): A` +error[E0275]: overflow evaluating the requirement `(): B` --> $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 + | +LL | impl B for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `()` to implement `BInd` +note: required for `()` to implement `A` + --> $DIR/mixed-cycles-2.rs:24:28 + | +LL | impl A for T {} + | ---- ^ ^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls_a` --> $DIR/mixed-cycles-2.rs:27:15 | diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs index ce7a380f07a..d11150ca55a 100644 --- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs @@ -25,7 +25,7 @@ fn foo() { // // https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 require_bar::(); - //~^ ERROR the trait bound `T: Bar` is not satisfied + //~^ ERROR type mismatch resolving `::Assoc == i32` } fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr index 2785357e792..3ef0afa38bf 100644 --- a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr @@ -1,19 +1,25 @@ -error[E0277]: the trait bound `T: Bar` is not satisfied +error[E0271]: type mismatch resolving `::Assoc == i32` --> $DIR/param-candidate-shadows-project.rs:27:19 | LL | require_bar::(); - | ^ the trait `Bar` is not implemented for `T` + | ^ type mismatch resolving `::Assoc == i32` | +note: types differ + --> $DIR/param-candidate-shadows-project.rs:10:18 + | +LL | type Assoc = i32; + | ^^^ +note: required for `T` to implement `Bar` + --> $DIR/param-candidate-shadows-project.rs:13:9 + | +LL | impl Bar for T where T: Foo {} + | ^^^ ^ ----------- unsatisfied trait bound introduced here note: required by a bound in `require_bar` --> $DIR/param-candidate-shadows-project.rs:15:19 | LL | fn require_bar() {} | ^^^ required by this bound in `require_bar` -help: consider further restricting this bound - | -LL | fn foo() { - | +++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 511111af83f..3d3fdc926f6 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR the trait bound `dyn Trait: Trait` is not satisfied + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 1b776d7198e..8cc2a51ee2b 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,9 +1,10 @@ -error[E0277]: the trait bound `dyn Trait: Trait` is not satisfied +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` --> $DIR/more-object-bound.rs:12:5 | LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | + = note: required because it appears within the type `dyn Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 | @@ -12,11 +13,7 @@ LL | fn foo(x: T::A) -> B LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement - | -LL | fn transmute(x: A) -> B where dyn Trait: Trait { - | ++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs index 40d68dbaffd..12ea1bf142a 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.rs @@ -24,7 +24,7 @@ fn needs_bar() {} fn foo + Foo>() { needs_bar::(); - //~^ ERROR type annotations needed: cannot satisfy `T: Bar` + //~^ ERROR type annotations needed: cannot satisfy `::Assoc == i32` } fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr index dfff9f11b87..21f3fbfeb87 100644 --- a/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr +++ b/tests/ui/traits/next-solver/normalize/two-projection-param-candidates-are-ambiguous.stderr @@ -1,11 +1,14 @@ -error[E0283]: type annotations needed: cannot satisfy `T: Bar` +error[E0284]: type annotations needed: cannot satisfy `::Assoc == i32` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:17 | LL | needs_bar::(); - | ^ + | ^ cannot satisfy `::Assoc == i32` | - = note: cannot satisfy `T: Bar` - = help: the trait `Bar` is implemented for `T` +note: required for `T` to implement `Bar` + --> $DIR/two-projection-param-candidates-are-ambiguous.rs:21:9 + | +LL | impl Bar for T where T: Foo {} + | ^^^ ^ ----------- unsatisfied trait bound introduced here note: required by a bound in `needs_bar` --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17 | @@ -14,4 +17,4 @@ LL | fn needs_bar() {} error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/object-unsafety.rs index 4222607b5bf..3aa1af4956e 100644 --- a/tests/ui/traits/next-solver/object-unsafety.rs +++ b/tests/ui/traits/next-solver/object-unsafety.rs @@ -11,9 +11,9 @@ fn copy(from: &U::From) -> U::From { pub fn copy_any(t: &T) -> T { copy::>(t) //~^ ERROR the type `& as Setup>::From` is not well-formed - //~| ERROR the trait bound `dyn Setup: Setup` is not satisfied //~| ERROR mismatched types //~| ERROR the type ` as Setup>::From` is not well-formed + //~| ERROR the trait bound `T: Copy` is not satisfied // FIXME(-Znext-solver): These error messages are horrible and some of them // are even simple fallout from previous error. diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index a9cbb721511..7c9a6077fe7 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -1,18 +1,19 @@ -error[E0277]: the trait bound `dyn Setup: Setup` is not satisfied +error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` --> $DIR/object-unsafety.rs:12:12 | LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup` + | ^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup: Setup` | + = note: required because it appears within the type `dyn Setup` note: required by a bound in `copy` --> $DIR/object-unsafety.rs:7:12 | LL | fn copy(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement +help: consider restricting type parameter `T` | -LL | pub fn copy_any(t: &T) -> T where dyn Setup: Setup { - | ++++++++++++++++++++++++++++++++ +LL | pub fn copy_any(t: &T) -> T { + | +++++++++++++++++++ error: the type `& as Setup>::From` is not well-formed --> $DIR/object-unsafety.rs:12:31 diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs index 186d0e8be56..052d803765d 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.rs @@ -15,5 +15,5 @@ fn impls() {} fn main() { impls::>(); - //~^ ERROR overflow evaluating the requirement `W<_>: Trait` + //~^ ERROR overflow evaluating the requirement `_: Sized` } diff --git a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr index b032ae3e740..6583cae8bb9 100644 --- a/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr +++ b/tests/ui/traits/next-solver/overflow/exponential-trait-goals.stderr @@ -1,9 +1,16 @@ -error[E0275]: overflow evaluating the requirement `W<_>: Trait` +error[E0275]: overflow evaluating the requirement `_: Sized` --> $DIR/exponential-trait-goals.rs:17:13 | LL | impls::>(); | ^^^^ | +note: required for `W<(W<_>, W<_>)>` to implement `Trait` + --> $DIR/exponential-trait-goals.rs:7:12 + | +LL | impl Trait for W<(W, W)> + | - ^^^^^ ^^^^^^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here note: required by a bound in `impls` --> $DIR/exponential-trait-goals.rs:14:13 | diff --git a/tests/ui/traits/next-solver/overflow/global-cache.stderr b/tests/ui/traits/next-solver/overflow/global-cache.stderr index 67616619384..1ef86abcebe 100644 --- a/tests/ui/traits/next-solver/overflow/global-cache.stderr +++ b/tests/ui/traits/next-solver/overflow/global-cache.stderr @@ -5,6 +5,15 @@ 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` + --> $DIR/global-cache.rs:12:16 + | +LL | impl Trait for Inc {} + | ----- ^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 3 redundant requirements hidden + = note: required for `Inc>>>>>>>>>>>>>>>` to implement `Trait` note: required by a bound in `impls_trait` --> $DIR/global-cache.rs:15:19 | From 34e91ece9033d0a354f1a42a67a69df9b46a27b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 2 May 2024 13:51:13 -0400 Subject: [PATCH 5/5] Higher ranked goal source, do overflow handling less badly --- compiler/rustc_middle/src/traits/solve.rs | 2 + .../src/traits/solve/inspect/format.rs | 1 + .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/solve/fulfill.rs | 151 +++++++++--------- .../src/solve/inspect/analyse.rs | 14 +- .../coherence-fulfill-overflow.stderr | 2 +- .../double-cycle-inductive-coinductive.stderr | 36 ++--- .../cycles/inductive-fixpoint-hang.stderr | 8 +- .../cycles/inductive-not-on-stack.rs | 4 +- .../cycles/inductive-not-on-stack.stderr | 36 ++--- .../next-solver/cycles/mixed-cycles-1.rs | 2 +- .../next-solver/cycles/mixed-cycles-1.stderr | 25 ++- .../next-solver/cycles/mixed-cycles-2.rs | 2 +- .../next-solver/cycles/mixed-cycles-2.stderr | 18 +-- .../next-solver/overflow/global-cache.stderr | 4 +- 15 files changed, 163 insertions(+), 144 deletions(-) diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 4c34bf88c7f..3ad6b68d129 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 2d73be387fd..11aa0e10931 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 35a3ac03a94..bae1c6b6011 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 d4fde60fd4a..796222129f1 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 de6c2322e8d..64a9a836b3d 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 1c2e445f63e..6e68646fbe4 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 0fe594bbb2d..86c71ad92ff 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 6211e08de70..ea46c0fea97 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 c3a3555f5ad..9d0ea51b1b2 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 75f82e998c7..fe02d3c407c 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 170446363ca..b90a354be1b 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 f785a9abc23..03e61dbf99c 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 3f9c290f706..a3ffcaafb37 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 c4071f2f56a..892426abe82 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 1ef86abcebe..9e467721e83 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