diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index b349df32574..d9e26a3cfd3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -264,7 +264,10 @@ where pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind { match (self.current_goal_kind, source) { - (CurrentGoalKind::CoinductiveTrait, GoalSource::ImplWhereBound) => PathKind::Coinductive, + (_, GoalSource::NormalizeGoal(step_kind)) => step_kind, + (CurrentGoalKind::CoinductiveTrait, GoalSource::ImplWhereBound) => { + PathKind::Coinductive + } _ => PathKind::Inductive, } } @@ -670,8 +673,11 @@ where #[instrument(level = "trace", skip(self))] pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal>) { - goal.predicate = - goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env)); + goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new( + self, + GoalSource::Misc, + goal.param_env, + )); self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal); self.nested_goals.normalizes_to_goals.push(goal); } @@ -679,7 +685,7 @@ where #[instrument(level = "debug", skip(self))] pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal) { goal.predicate = - goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env)); + goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env)); self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); self.nested_goals.goals.push((source, goal)); } @@ -1100,6 +1106,7 @@ where { ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv, + normalization_goal_source: GoalSource, cache: HashMap, } @@ -1108,8 +1115,18 @@ where D: SolverDelegate, I: Interner, { - fn new(ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv) -> Self { - ReplaceAliasWithInfer { ecx, param_env, cache: Default::default() } + fn new( + ecx: &'me mut EvalCtxt<'a, D>, + for_goal_source: GoalSource, + param_env: I::ParamEnv, + ) -> Self { + let step_kind = ecx.step_kind_for_source(for_goal_source); + ReplaceAliasWithInfer { + ecx, + param_env, + normalization_goal_source: GoalSource::NormalizeGoal(step_kind), + cache: Default::default(), + } } } @@ -1132,7 +1149,7 @@ where ty::AliasRelationDirection::Equate, ); self.ecx.add_goal( - GoalSource::Misc, + self.normalization_goal_source, Goal::new(self.cx(), self.param_env, normalizes_to), ); infer_ty @@ -1161,7 +1178,7 @@ where ty::AliasRelationDirection::Equate, ); self.ecx.add_goal( - GoalSource::Misc, + self.normalization_goal_source, Goal::new(self.cx(), self.param_env, normalizes_to), ); infer_ct diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 982782bc57c..4f177df89e2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -438,7 +438,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { let obligation; match (child_mode, nested_goal.source()) { - (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => { + ( + ChildMode::Trait(_) | ChildMode::Host(_), + GoalSource::Misc | GoalSource::NormalizeGoal(_), + ) => { continue; } (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 0cf8cfb879f..18e84db5d68 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -19,6 +19,8 @@ use std::marker::PhantomData; use derive_where::derive_where; use rustc_index::{Idx, IndexVec}; +#[cfg(feature = "nightly")] +use rustc_macros::HashStable_NoContext; use tracing::debug; use crate::data_structures::HashMap; @@ -109,7 +111,8 @@ pub trait Delegate { /// In the initial iteration of a cycle, we do not yet have a provisional /// result. In the case we return an initial provisional result depending /// on the kind of cycle. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum PathKind { Coinductive, Inductive, diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index a562b751d8a..25081976c9e 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -8,6 +8,7 @@ use derive_where::derive_where; use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use crate::search_graph::PathKind; use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; pub type CanonicalInput::Predicate> = @@ -78,6 +79,14 @@ pub enum GoalSource { /// This is used in two places: projecting to an opaque whose hidden type /// is already registered in the opaque type storage, and for rigid projections. AliasWellFormed, + + /// In case normalizing aliases in nested goals cycles, eagerly normalizing these + /// aliases in the context of the parent may incorrectly change the cycle kind. + /// Normalizing aliases in goals therefore tracks the original path kind for this + /// nested goal. + /// + /// This is necessary for tests/ui/sized/coinductive-1.rs to compile. + NormalizeGoal(PathKind), } #[derive_where(Clone; I: Interner, Goal: Clone)] diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index c497f1b6d0b..94f06bbbbc4 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -6,30 +6,90 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` +error[E0275]: overflow evaluating the requirement `&T: ~const ConstName` + --> $DIR/issue-88119.rs:19:49 + | +LL | impl const ConstName for &T + | ^^ + +error[E0275]: overflow evaluating the requirement `&T: ConstName` + --> $DIR/issue-88119.rs:19:49 + | +LL | impl const ConstName for &T + | ^^ + +error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` --> $DIR/issue-88119.rs:21:5 | LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` + | ^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` + +error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` --> $DIR/issue-88119.rs:21:10 | LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` + | ^^^^^^^^^^^^^^^ + | +note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` -error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` +error[E0275]: overflow evaluating the requirement `&mut T: ~const ConstName` + --> $DIR/issue-88119.rs:26:49 + | +LL | impl const ConstName for &mut T + | ^^^^^^ + +error[E0275]: overflow evaluating the requirement `&mut T: ConstName` + --> $DIR/issue-88119.rs:26:49 + | +LL | impl const ConstName for &mut T + | ^^^^^^ + +error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` --> $DIR/issue-88119.rs:28:5 | LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` + | ^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` + +error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` --> $DIR/issue-88119.rs:28:10 | LL | [(); name_len::()]:, - | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` + | ^^^^^^^^^^^^^^^ + | +note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:5 + | +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` -error: aborting due to 3 previous errors +error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName` + --> $DIR/issue-88119.rs:33:35 + | +LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES; + | ^^^^^^^^ -For more information about this error, try `rustc --explain E0284`. +error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName` + --> $DIR/issue-88119.rs:34:35 + | +LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; + | ^^^^^^^^ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/sized/coinductive-1.rs b/tests/ui/sized/coinductive-1.rs index 3c1ee557af7..42dd8d1f604 100644 --- a/tests/ui/sized/coinductive-1.rs +++ b/tests/ui/sized/coinductive-1.rs @@ -1,4 +1,7 @@ //@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver struct Node>(C::Assoc); trait Trait { diff --git a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.current.stderr b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.current.stderr new file mode 100644 index 00000000000..dd9f7d89aa1 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.current.stderr @@ -0,0 +1,23 @@ +error[E0275]: overflow evaluating the requirement `Vec: Trait` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `Vec` to implement `Trait` + --> $DIR/item-bound-via-impl-where-clause.rs:22:12 + | +LL | impl Trait for L + | ^^^^^^^^ ^ +LL | where +LL | L: Trait, + | -------- unsatisfied trait bound introduced here +note: required by a bound in `transmute` + --> $DIR/item-bound-via-impl-where-clause.rs:29:17 + | +LL | fn transmute, R>(r: L) -> >::Proof { r } + | ^^^^^^^^ required by this bound in `transmute` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr new file mode 100644 index 00000000000..451c1442ed2 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.next.stderr @@ -0,0 +1,49 @@ +error[E0275]: overflow evaluating the requirement `Vec: Trait` + --> $DIR/item-bound-via-impl-where-clause.rs:31:33 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^ + | +note: required by a bound in `transmute` + --> $DIR/item-bound-via-impl-where-clause.rs:29:17 + | +LL | fn transmute, R>(r: L) -> >::Proof { r } + | ^^^^^^^^ required by this bound in `transmute` + +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == String` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof: Sized` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the return type of a function must have a statically known size + +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof well-formed` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` + --> $DIR/item-bound-via-impl-where-clause.rs:31:21 + | +LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs new file mode 100644 index 00000000000..39381d17f7a --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/coinduction/item-bound-via-impl-where-clause.rs @@ -0,0 +1,39 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// A variation of #135246 where the cyclic bounds are part of +// the impl instead of the impl associated item. + +trait Trait: Sized { + type Proof: Trait; +} + +// We need to use indirection here as we otherwise normalize +// `>::Proof` before recursing into +// `R: Trait>::Proof>`. +trait Indir, R>: Trait>::Proof> {} +impl Indir for R +where + L: Trait, + R: Trait>::Proof>, +{} + +impl Trait for L +where + L: Trait, + R: Indir, + { + type Proof = R; +} +fn transmute, R>(r: L) -> >::Proof { r } +fn main() { + let s: String = transmute::<_, String>(vec![65_u8, 66, 67]); + //~^ ERROR overflow evaluating the requirement `Vec: Trait` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == String` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof: Sized` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof well-formed` + //[next]~| ERROR overflow evaluating the requirement `< as Trait>::Proof as Trait>::Proof == _` + println!("{}", s); // ABC +} diff --git a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.stderr b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.current.stderr similarity index 100% rename from tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.stderr rename to tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.current.stderr diff --git a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.next.stderr b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.next.stderr new file mode 100644 index 00000000000..50dcea0bfac --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.next.stderr @@ -0,0 +1,10 @@ +error[E0391]: cycle detected when computing layout of `<[Hello] as Normalize>::Assoc` + | + = note: ...which requires computing layout of `Hello`... + = note: ...which again requires computing layout of `<[Hello] as Normalize>::Assoc`, completing the cycle + = note: cycle used when computing layout of `Hello` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs index 197207dfb4b..5b7bf5f3404 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs @@ -1,6 +1,10 @@ // Regression test for #129541 //~^ ERROR cycle detected when computing layout of `<[Hello] as Normalize>::Assoc` [E0391] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + trait Bound {} trait Normalize { type Assoc; diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple_curr.stderr similarity index 100% rename from tests/ui/traits/solver-cycles/129541-recursive-struct.multiple.stderr rename to tests/ui/traits/solver-cycles/129541-recursive-struct.multiple_curr.stderr diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.multiple_next.stderr similarity index 100% rename from tests/ui/traits/solver-cycles/129541-recursive-struct.unique.stderr rename to tests/ui/traits/solver-cycles/129541-recursive-struct.multiple_next.stderr diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index 729771e560e..1f5d0a772a2 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -1,6 +1,9 @@ // Regression test for #129541 -//@ revisions: unique multiple +//@ revisions: unique_curr unique_next multiple_curr multiple_next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[unique_next] compile-flags: -Znext-solver +//@[multiple_next] compile-flags: -Znext-solver //@ error-pattern: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` trait Bound {} @@ -8,7 +11,7 @@ trait Normalize { type Assoc; } -#[cfg(multiple)] +#[cfg(any(multiple_curr, multiple_next))] impl Normalize for T { type Assoc = T; } diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_curr.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_curr.stderr new file mode 100644 index 00000000000..93b064cdce2 --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_curr.stderr @@ -0,0 +1,6 @@ +error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_next.stderr b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_next.stderr new file mode 100644 index 00000000000..93b064cdce2 --- /dev/null +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.unique_next.stderr @@ -0,0 +1,6 @@ +error: reached the recursion limit finding the struct tail for `<[Hello] as Normalize>::Assoc` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: aborting due to 1 previous error +