Skip to content

Commit a952c87

Browse files
nikomatsakisflodiebold
authored andcommitted
add some more projection tests
1 parent 72be500 commit a952c87

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

tests/test/projection.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ fn projection_equality() {
136136
}
137137
}
138138

139+
goal {
140+
exists<U> {
141+
S: Trait1<Type = U>
142+
}
143+
} yields[SolverChoice::slg_default()] {
144+
// this is wrong, chalk#234
145+
"Ambiguous"
146+
} yields[SolverChoice::recursive()] {
147+
"Unique; substitution [?0 := u32]"
148+
}
149+
139150
goal {
140151
exists<U> {
141152
S: Trait2<U>
@@ -149,6 +160,127 @@ fn projection_equality() {
149160
}
150161
}
151162

163+
#[test]
164+
fn projection_equality_priority1() {
165+
test! {
166+
program {
167+
trait Trait1<T> {
168+
type Type;
169+
}
170+
171+
struct u32 {}
172+
struct S1 {}
173+
struct S2 {}
174+
struct S3 {}
175+
176+
impl Trait1<S2> for S1 {
177+
type Type = u32;
178+
}
179+
}
180+
181+
goal {
182+
exists<T, U> {
183+
S1: Trait1<T, Type = U>
184+
}
185+
} yields[SolverChoice::slg_default()] {
186+
// this is wrong, chalk#234
187+
"Ambiguous"
188+
} yields[SolverChoice::recursive()] {
189+
// This is.. interesting, but not necessarily wrong.
190+
// It's certainly true that based on the impls we see
191+
// the only possible value for `U` is `u32`.
192+
//
193+
// Can we come to any harm by inferring that `T = S2`
194+
// here, even though we could've chosen to say that
195+
// `U = !<S1 as Trait1<T>>::Type` and thus not
196+
// constrained `T` at all? I can't come up with
197+
// an example where that's the case, so maybe
198+
// not. -Niko
199+
"Unique; substitution [?0 := S2, ?1 := u32]"
200+
}
201+
}
202+
}
203+
204+
#[test]
205+
fn projection_equality_priority2() {
206+
test! {
207+
program {
208+
trait Trait1<T> {
209+
type Type;
210+
}
211+
212+
struct u32 {}
213+
struct S1 {}
214+
struct S2 {}
215+
struct S3 {}
216+
217+
impl<X> Trait1<S1> for X {
218+
type Type = u32;
219+
}
220+
}
221+
222+
goal {
223+
forall<X, Y> {
224+
if (X: Trait1<Y>) {
225+
exists<Out1, Out2> {
226+
X: Trait1<Out1, Type = Out2>
227+
}
228+
}
229+
}
230+
} yields {
231+
// Correct: Ambiguous because Out1 = Y and Out1 = S1 are both value.
232+
"Ambiguous; no inference guidance"
233+
}
234+
235+
goal {
236+
forall<X, Y> {
237+
if (X: Trait1<Y>) {
238+
exists<Out1, Out2> {
239+
X: Trait1<Out1, Type = Out2>,
240+
Out1 = Y
241+
}
242+
}
243+
}
244+
} yields {
245+
// Constraining Out1 = Y gives us only one choice.
246+
"Unique; substitution [?0 := !1_1, ?1 := (Trait1::Type)<!1_0, !1_1>], lifetime constraints []"
247+
}
248+
249+
goal {
250+
forall<X, Y> {
251+
if (X: Trait1<Y>) {
252+
exists<Out1, Out2> {
253+
Out1 = Y,
254+
X: Trait1<Out1, Type = Out2>
255+
}
256+
}
257+
}
258+
} yields {
259+
// Constraining Out1 = Y gives us only one choice.
260+
"Unique; substitution [?0 := !1_1, ?1 := (Trait1::Type)<!1_0, !1_1>], lifetime constraints []"
261+
}
262+
263+
goal {
264+
forall<X, Y> {
265+
if (X: Trait1<Y>) {
266+
exists<Out1, Out2> {
267+
Out1 = S1,
268+
X: Trait1<Out1, Type = Out2>
269+
}
270+
}
271+
}
272+
} yields[SolverChoice::slg_default()] {
273+
// chalk#234: Constraining Out1 = S1 gives us only the choice to
274+
// use the impl, but the SLG solver can't decide between
275+
// the placeholder and the normalized form.
276+
"Ambiguous; definite substitution for<?U1> { [?0 := S1, ?1 := ^0.0] }"
277+
} yields[SolverChoice::recursive()] {
278+
// Constraining Out1 = S1 gives us only one choice, use the impl,
279+
// and the recursive solver prefers the normalized form.
280+
"Unique; substitution [?0 := S1, ?1 := u32], lifetime constraints []"
281+
}
282+
}
283+
}
152284
#[test]
153285
fn projection_equality_from_env() {
154286
test! {

0 commit comments

Comments
 (0)