Skip to content

Commit 1171683

Browse files
committed
instantiate response: no unnecessary new universe
this previously was a off-by-one error.
1 parent d06ca0f commit 1171683

File tree

4 files changed

+158
-1
lines changed

4 files changed

+158
-1
lines changed

compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
215215
// created inside of the query directly instead of returning them to the
216216
// caller.
217217
let prev_universe = self.infcx.universe();
218-
let universes_created_in_query = response.max_universe.index() + 1;
218+
let universes_created_in_query = response.max_universe.index();
219219
for _ in 0..universes_created_in_query {
220220
self.infcx.create_next_universe();
221221
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
// A minimization of an ambiguity when using typenum. See
5+
// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
6+
// for more details.
7+
trait Id {
8+
type Assoc: ?Sized;
9+
}
10+
impl<T: ?Sized> Id for T {
11+
type Assoc = T;
12+
}
13+
14+
trait WithAssoc<T: ?Sized> {
15+
type Assoc: ?Sized;
16+
}
17+
18+
19+
struct Leaf;
20+
struct Wrapper<U: ?Sized>(U);
21+
22+
impl<U: ?Sized> WithAssoc<U> for Leaf {
23+
type Assoc = U;
24+
}
25+
26+
impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
27+
where
28+
Ul: WithAssoc<Ur>,
29+
{
30+
type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
31+
}
32+
33+
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
34+
where
35+
T: WithAssoc<U, Assoc = V>,
36+
{
37+
}
38+
39+
// normalize self type to `Wrapper<Leaf>`
40+
// This succeeds, HOWEVER, instantiating the query response previously
41+
// incremented the universe index counter.
42+
// equate impl headers:
43+
// <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
44+
// <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
45+
// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
46+
// add where bounds:
47+
// ~> Leaf: WithAssoc<?3t>
48+
// equate with assoc type:
49+
// ?0t
50+
// <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
51+
// ~> AliasRelate(
52+
// <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
53+
// Equate,
54+
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
55+
// )
56+
//
57+
// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
58+
// it after incrementing the universe index while normalizing the self type.
59+
//
60+
// evaluate_added_goals_and_make_query_response:
61+
// AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
62+
// YES, constrains ?3t to Leaf
63+
// AliasRelate(
64+
// <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
65+
// Equate,
66+
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
67+
// )
68+
//
69+
// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
70+
// results in ambiguity.
71+
fn main() {
72+
bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// compile-flags: -Ztrait-solver=next
2+
3+
// Generalizing a projection containing an inference variable
4+
// which cannot be named by the `root_vid` can result in ambiguity.
5+
//
6+
// Because we do not decrement the universe index when exiting a forall,
7+
// this can cause unexpected failures.
8+
//
9+
// See generalize-proj-new-universe-index-1.rs for more details.
10+
11+
// For this reproduction we need:
12+
// - an inference variable with a lower universe
13+
// - enter a binder to increment the current universe
14+
// - create a new inference variable which is constrained by proving a goal
15+
// - equate a projection containing the new variable with the first variable
16+
// - generalization creates yet another inference variable which is then
17+
// part of an alias-relate, resulting this to fail with ambiguity.
18+
//
19+
// Because we need to enter the binder in-between the creation of the first
20+
// and second inference variable, this is easiest via
21+
// `assemble_candidates_after_normalizing_self_ty` because eagerly call
22+
// `try_evaluate_added_goals` there before creating the inference variables
23+
// for the impl parameters.
24+
trait Id {
25+
type Assoc: ?Sized;
26+
}
27+
impl<T: ?Sized> Id for T {
28+
type Assoc = T;
29+
}
30+
31+
// By adding an higher ranked bound to the impl we currently
32+
// propagate this bound to the caller, forcing us to create a new
33+
// universe.
34+
trait IdHigherRankedBound {
35+
type Assoc: ?Sized;
36+
}
37+
38+
impl<T: ?Sized> IdHigherRankedBound for T
39+
where
40+
for<'a> T: 'a,
41+
{
42+
type Assoc = T;
43+
}
44+
45+
trait WithAssoc<T: ?Sized> {
46+
type Assoc: ?Sized;
47+
}
48+
49+
50+
struct Leaf;
51+
struct Wrapper<U: ?Sized>(U);
52+
struct Rigid;
53+
54+
impl<U: ?Sized> WithAssoc<U> for Leaf {
55+
type Assoc = U;
56+
}
57+
58+
59+
impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
60+
where
61+
Leaf: WithAssoc<Ur>,
62+
{
63+
type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
64+
}
65+
66+
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
67+
where
68+
T: WithAssoc<U, Assoc = V>,
69+
{
70+
}
71+
72+
fn main() {
73+
bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
74+
//~^ ERROR type annotations needed
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/generalize-proj-new-universe-index-2.rs:72:5
3+
|
4+
LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)