From 360bd321bcb3600125ea811dcf6dc09bb860ef69 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 23 Dec 2024 20:17:53 +0000 Subject: [PATCH] Recurse on GAT where clauses in fulfillment error proof tree visitor --- .../src/solve/effect_goals.rs | 4 ++-- .../rustc_trait_selection/src/solve/fulfill.rs | 14 +++++++++----- compiler/rustc_type_ir/src/solve/mod.rs | 4 ++++ .../assoc-type-const-bound-usage-fail-2.rs | 4 ++-- .../assoc-type-const-bound-usage-fail-2.stderr | 4 ++-- .../assoc-type-const-bound-usage-fail.rs | 4 ++-- .../assoc-type-const-bound-usage-fail.stderr | 4 ++-- .../ui/traits/const-traits/const-opaque.no.stderr | 2 +- tests/ui/traits/const-traits/const-opaque.rs | 2 +- 9 files changed, 25 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 281796e84b169..7669a305d58d1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -103,7 +103,7 @@ where |ecx| { // Const conditions must hold for the implied const bound to hold. ecx.add_goals( - GoalSource::Misc, + GoalSource::AliasBoundConstCondition, cx.const_conditions(alias_ty.def_id) .iter_instantiated(cx, alias_ty.args) .map(|trait_ref| { @@ -353,7 +353,7 @@ where ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { ecx.add_goals( - GoalSource::ImplWhereBound, + GoalSource::AliasBoundConstCondition, const_conditions.into_iter().map(|trait_ref| { goal.with( cx, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7aa82c52c9f26..986176aca770e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -413,6 +413,7 @@ impl<'tcx> BestObligation<'tcx> { matches!( nested_goal.source(), GoalSource::ImplWhereBound + | GoalSource::AliasBoundConstCondition | GoalSource::InstantiateHigherRanked | GoalSource::AliasWellFormed ) && match self.consider_ambiguities { @@ -495,7 +496,6 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { }; let mut impl_where_bound_count = 0; - let mut impl_const_condition_bound_count = 0; for nested_goal in candidate.instantiate_nested_goals(self.span()) { trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); @@ -521,21 +521,25 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { )); impl_where_bound_count += 1; } - (ChildMode::Host(parent_host_pred), GoalSource::ImplWhereBound) => { + ( + ChildMode::Host(parent_host_pred), + GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, + ) => { obligation = make_obligation(derive_host_cause( tcx, candidate.kind(), self.obligation.cause.clone(), - impl_const_condition_bound_count, + impl_where_bound_count, parent_host_pred, )); - impl_const_condition_bound_count += 1; + impl_where_bound_count += 1; } // Skip over a higher-ranked predicate. (_, GoalSource::InstantiateHigherRanked) => { obligation = self.obligation.clone(); } - (ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => { + (ChildMode::PassThrough, _) + | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { obligation = make_obligation(self.obligation.cause.clone()); } } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 8fe512026e5d9..1ae904d50e066 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -68,6 +68,10 @@ pub enum GoalSource { /// FIXME(-Znext-solver=coinductive): Explain how and why this /// changes whether cycles are coinductive. ImplWhereBound, + /// Const conditions that need to hold for `~const` alias bounds to hold. + /// + /// FIXME(-Znext-solver=coinductive): Are these even coinductive? + AliasBoundConstCondition, /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, /// Predicate required for an alias projection to be well-formed. diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs index b3a636b0f713d..28072b725b636 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs @@ -21,9 +21,9 @@ trait Other {} const fn fails() { T::Assoc::::func(); - //~^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied + //~^ ERROR the trait bound `U: ~const Other` is not satisfied ::Assoc::::func(); - //~^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied + //~^ ERROR the trait bound `U: ~const Other` is not satisfied } const fn works() { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr index c7af0a220ca31..6da69a9c710ce 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr @@ -1,10 +1,10 @@ -error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied +error[E0277]: the trait bound `U: ~const Other` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ -error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied +error[E0277]: the trait bound `U: ~const Other` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | ::Assoc::::func(); diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs index fe375b25b8c8c..ce01086f0dc0b 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs @@ -14,9 +14,9 @@ trait Trait { const fn unqualified() { T::Assoc::func(); - //~^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied + //~^ ERROR the trait bound `T: ~const Trait` is not satisfied ::Assoc::func(); - //~^ ERROR the trait bound `::Assoc: ~const Trait` is not satisfied + //~^ ERROR the trait bound `T: ~const Trait` is not satisfied } const fn works() { diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr index ce355083b90e4..99fc924ad06b9 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr @@ -1,10 +1,10 @@ -error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied +error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); | ^^^^^^^^ -error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied +error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | ::Assoc::func(); diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr index 33aa1065df356..1278e1257467b 100644 --- a/tests/ui/traits/const-traits/const-opaque.no.stderr +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -12,7 +12,7 @@ note: required by a bound in `bar` LL | const fn bar(t: T) -> impl ~const Foo { | ^^^^^^ required by this bound in `bar` -error[E0277]: the trait bound `impl Foo: const Foo` is not satisfied +error[E0277]: the trait bound `(): const Foo` is not satisfied --> $DIR/const-opaque.rs:33:12 | LL | opaque.method(); diff --git a/tests/ui/traits/const-traits/const-opaque.rs b/tests/ui/traits/const-traits/const-opaque.rs index bfcadd521a54e..96cdd7d9f2619 100644 --- a/tests/ui/traits/const-traits/const-opaque.rs +++ b/tests/ui/traits/const-traits/const-opaque.rs @@ -31,7 +31,7 @@ const _: () = { let opaque = bar(()); //[no]~^ ERROR the trait bound `(): const Foo` is not satisfied opaque.method(); - //[no]~^ ERROR the trait bound `impl Foo: const Foo` is not satisfied + //[no]~^ ERROR the trait bound `(): const Foo` is not satisfied std::mem::forget(opaque); };