instantiate response: no unnecessary new universe
this previously was a off-by-one error.
This commit is contained in:
parent
d06ca0ffaf
commit
11716830ac
4 changed files with 158 additions and 1 deletions
|
@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
// created inside of the query directly instead of returning them to the
|
// created inside of the query directly instead of returning them to the
|
||||||
// caller.
|
// caller.
|
||||||
let prev_universe = self.infcx.universe();
|
let prev_universe = self.infcx.universe();
|
||||||
let universes_created_in_query = response.max_universe.index() + 1;
|
let universes_created_in_query = response.max_universe.index();
|
||||||
for _ in 0..universes_created_in_query {
|
for _ in 0..universes_created_in_query {
|
||||||
self.infcx.create_next_universe();
|
self.infcx.create_next_universe();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
// A minimization of an ambiguity when using typenum. See
|
||||||
|
// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
|
||||||
|
// for more details.
|
||||||
|
trait Id {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
impl<T: ?Sized> Id for T {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait WithAssoc<T: ?Sized> {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Leaf;
|
||||||
|
struct Wrapper<U: ?Sized>(U);
|
||||||
|
|
||||||
|
impl<U: ?Sized> WithAssoc<U> for Leaf {
|
||||||
|
type Assoc = U;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
|
||||||
|
where
|
||||||
|
Ul: WithAssoc<Ur>,
|
||||||
|
{
|
||||||
|
type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
|
||||||
|
where
|
||||||
|
T: WithAssoc<U, Assoc = V>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize self type to `Wrapper<Leaf>`
|
||||||
|
// This succeeds, HOWEVER, instantiating the query response previously
|
||||||
|
// incremented the universe index counter.
|
||||||
|
// equate impl headers:
|
||||||
|
// <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
|
||||||
|
// <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
|
||||||
|
// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
|
||||||
|
// add where bounds:
|
||||||
|
// ~> Leaf: WithAssoc<?3t>
|
||||||
|
// equate with assoc type:
|
||||||
|
// ?0t
|
||||||
|
// <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
|
||||||
|
// ~> AliasRelate(
|
||||||
|
// <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
|
||||||
|
// Equate,
|
||||||
|
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
|
||||||
|
// it after incrementing the universe index while normalizing the self type.
|
||||||
|
//
|
||||||
|
// evaluate_added_goals_and_make_query_response:
|
||||||
|
// AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
|
||||||
|
// YES, constrains ?3t to Leaf
|
||||||
|
// AliasRelate(
|
||||||
|
// <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
|
||||||
|
// Equate,
|
||||||
|
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
|
||||||
|
// results in ambiguity.
|
||||||
|
fn main() {
|
||||||
|
bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
|
||||||
|
// Generalizing a projection containing an inference variable
|
||||||
|
// which cannot be named by the `root_vid` can result in ambiguity.
|
||||||
|
//
|
||||||
|
// Because we do not decrement the universe index when exiting a forall,
|
||||||
|
// this can cause unexpected failures.
|
||||||
|
//
|
||||||
|
// See generalize-proj-new-universe-index-1.rs for more details.
|
||||||
|
|
||||||
|
// For this reproduction we need:
|
||||||
|
// - an inference variable with a lower universe
|
||||||
|
// - enter a binder to increment the current universe
|
||||||
|
// - create a new inference variable which is constrained by proving a goal
|
||||||
|
// - equate a projection containing the new variable with the first variable
|
||||||
|
// - generalization creates yet another inference variable which is then
|
||||||
|
// part of an alias-relate, resulting this to fail with ambiguity.
|
||||||
|
//
|
||||||
|
// Because we need to enter the binder in-between the creation of the first
|
||||||
|
// and second inference variable, this is easiest via
|
||||||
|
// `assemble_candidates_after_normalizing_self_ty` because eagerly call
|
||||||
|
// `try_evaluate_added_goals` there before creating the inference variables
|
||||||
|
// for the impl parameters.
|
||||||
|
trait Id {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
impl<T: ?Sized> Id for T {
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// By adding an higher ranked bound to the impl we currently
|
||||||
|
// propagate this bound to the caller, forcing us to create a new
|
||||||
|
// universe.
|
||||||
|
trait IdHigherRankedBound {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> IdHigherRankedBound for T
|
||||||
|
where
|
||||||
|
for<'a> T: 'a,
|
||||||
|
{
|
||||||
|
type Assoc = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait WithAssoc<T: ?Sized> {
|
||||||
|
type Assoc: ?Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Leaf;
|
||||||
|
struct Wrapper<U: ?Sized>(U);
|
||||||
|
struct Rigid;
|
||||||
|
|
||||||
|
impl<U: ?Sized> WithAssoc<U> for Leaf {
|
||||||
|
type Assoc = U;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
|
||||||
|
where
|
||||||
|
Leaf: WithAssoc<Ur>,
|
||||||
|
{
|
||||||
|
type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
|
||||||
|
where
|
||||||
|
T: WithAssoc<U, Assoc = V>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||||
|
//~^ ERROR type annotations needed
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/generalize-proj-new-universe-index-2.rs:72:5
|
||||||
|
|
|
||||||
|
LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
Loading…
Add table
Add a link
Reference in a new issue