summaryrefslogtreecommitdiffstats
path: root/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs
blob: 6fea409ed4716244a484c2ba1c86f3ff4c86e76c (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// This test examines the error spans reported when a generic `impl` fails.
// For example, if a function wants an `Option<T>` where `T: Copy` but you pass `Some(vec![1, 2])`,
// then we want to point at the `vec![1, 2]` and not the `Some( ... )` expression.

trait T1 {}
trait T2 {}
trait T3 {}
trait T4 {}

impl T2 for i32 {}
impl T3 for i32 {}

struct Wrapper<W> {
    value: W,
}
impl<B: T2> T1 for Wrapper<B> {}

struct Burrito<F> {
    spicy: bool,
    filling: F,
}
impl<A: T3> T2 for Burrito<A> {}

struct BurritoTuple<F>(F);
impl<C: T3> T2 for BurritoTuple<C> {}

enum BurritoKinds<G> {
    SmallBurrito { spicy: bool, small_filling: G },
    LargeBurrito { spicy: bool, large_filling: G },
    MultiBurrito { first_filling: G, second_filling: G },
}
impl<D: T3> T2 for BurritoKinds<D> {}

struct Taco<H>(bool, H);
impl<E: T3> T2 for Taco<E> {}

enum TacoKinds<H> {
    OneTaco(bool, H),
    TwoTacos(bool, H, H),
}
impl<F: T3> T2 for TacoKinds<F> {}

struct GenericBurrito<Spiciness, Filling> {
    spiciness: Spiciness,
    filling: Filling,
}
impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
struct NotSpicy;

impl<A: T3, B: T3> T2 for (A, B) {}
impl<A: T2, B: T2> T1 for (A, B) {}

fn want<V: T1>(_x: V) {}

// Some more-complex examples:
type AliasBurrito<T> = GenericBurrito<T, T>;

// The following example is fairly confusing. The idea is that we want to "misdirect" the location
// of the error.

struct Two<A, B> {
    a: A,
    b: B,
}

impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}

struct DoubleWrapper<T> {
    item: Wrapper<T>,
}

impl<T: T1> T1 for DoubleWrapper<T> {}

impl<'a, T: T2> T1 for &'a T {}

fn example<Q>(q: Q) {
    // In each of the following examples, we expect the error span to point at the 'q' variable,
    // since the missing constraint is `Q: T3`.

    // Verifies for struct:
    want(Wrapper { value: Burrito { spicy: false, filling: q } });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for enum with named fields in variant:
    want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for tuple struct:
    want(Wrapper { value: Taco(false, q) });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for tuple enum variant:
    want(Wrapper { value: TacoKinds::OneTaco(false, q) });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for generic type with multiple parameters:
    want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for tuple:
    want((3, q));
    //~^ ERROR the trait bound `Q: T2` is not satisfied [E0277]

    // Verifies for nested tuple:
    want(Wrapper { value: (3, q) });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    // Verifies for nested tuple:
    want(((3, q), 5));
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    want(DoubleWrapper { item: Wrapper { value: q } });
    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]

    want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]

    // Verifies for type alias to struct:
    want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]

    want(Two { a: Two { a: (), b: q }, b: () });
    //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]

    // We *should* blame the 'q'.
    // FIXME: Right now, the wrong field is blamed.
    want(
        Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
        //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
    );

    // Verifies for reference:
    want(&Burrito { spicy: false, filling: q });
    //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
}

fn main() {}