normalizing where-clauses is also coinductive, add tests
This commit is contained in:
parent
a7970c0b27
commit
7eb677e7eb
17 changed files with 255 additions and 20 deletions
|
@ -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<I, ty::NormalizesTo<I>>) {
|
||||
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<I, I::Predicate>) {
|
||||
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<I::Ty, I::Ty>,
|
||||
}
|
||||
|
||||
|
@ -1108,8 +1115,18 @@ where
|
|||
D: SolverDelegate<Interner = I>,
|
||||
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
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<I, T = <I as Interner>::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<I, P>: Clone)]
|
||||
|
|
|
@ -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::<T>()` can be evaluated`
|
||||
error[E0275]: overflow evaluating the requirement `&T: ~const ConstName`
|
||||
--> $DIR/issue-88119.rs:19:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `&T: ConstName`
|
||||
--> $DIR/issue-88119.rs:19:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
|
||||
--> $DIR/issue-88119.rs:21:5
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `<&T as ConstName>`
|
||||
--> $DIR/issue-88119.rs:21:5
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
|
||||
--> $DIR/issue-88119.rs:21:10
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^ 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::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
error[E0275]: overflow evaluating the requirement `&mut T: ~const ConstName`
|
||||
--> $DIR/issue-88119.rs:26:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `&mut T: ConstName`
|
||||
--> $DIR/issue-88119.rs:26:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
|
||||
--> $DIR/issue-88119.rs:28:5
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required by a bound in `<&mut T as ConstName>`
|
||||
--> $DIR/issue-88119.rs:28:5
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
|
||||
--> $DIR/issue-88119.rs:28:10
|
||||
|
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^ 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::<T>()]:,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ 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`.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
struct Node<C: Trait<Self>>(C::Assoc);
|
||||
|
||||
trait Trait<T> {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
error[E0275]: overflow evaluating the requirement `Vec<u8>: Trait<String>`
|
||||
--> $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<u8>` to implement `Trait<String>`
|
||||
--> $DIR/item-bound-via-impl-where-clause.rs:22:12
|
||||
|
|
||||
LL | impl<L, R> Trait<R> for L
|
||||
| ^^^^^^^^ ^
|
||||
LL | where
|
||||
LL | L: Trait<R>,
|
||||
| -------- 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<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::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`.
|
|
@ -0,0 +1,49 @@
|
|||
error[E0275]: overflow evaluating the requirement `Vec<u8>: Trait<String>`
|
||||
--> $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<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
|
||||
| ^^^^^^^^ required by this bound in `transmute`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::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 `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::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 `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::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 `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::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 `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::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`.
|
|
@ -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<R>: Sized {
|
||||
type Proof: Trait<R, Proof = Self>;
|
||||
}
|
||||
|
||||
// We need to use indirection here as we otherwise normalize
|
||||
// `<L::Proof as Trait<R>>::Proof` before recursing into
|
||||
// `R: Trait<R, Proof = <L::Proof as Trait<R>>::Proof>`.
|
||||
trait Indir<L: Trait<R>, R>: Trait<R, Proof = <L::Proof as Trait<R>>::Proof> {}
|
||||
impl<L, R> Indir<L, R> for R
|
||||
where
|
||||
L: Trait<R>,
|
||||
R: Trait<R, Proof = <L::Proof as Trait<R>>::Proof>,
|
||||
{}
|
||||
|
||||
impl<L, R> Trait<R> for L
|
||||
where
|
||||
L: Trait<R>,
|
||||
R: Indir<L, R>,
|
||||
{
|
||||
type Proof = R;
|
||||
}
|
||||
fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
|
||||
fn main() {
|
||||
let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
|
||||
//~^ ERROR overflow evaluating the requirement `Vec<u8>: Trait<String>`
|
||||
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
|
||||
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == String`
|
||||
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof: Sized`
|
||||
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof well-formed`
|
||||
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
|
||||
println!("{}", s); // ABC
|
||||
}
|
|
@ -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`.
|
|
@ -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;
|
||||
|
|
|
@ -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<T: Bound> Normalize for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue