summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/next-solver/generalize/generalize-proj-new-universe-index-2.rs
blob: 70758e7deaace97cf77a9b5163bf735de2aff5a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// compile-flags: -Znext-solver
// known-bug: trait-system-refactor-initiative#60

// 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, _>()
}