Skip to content

Commit ecf20dc

Browse files
super-tupledaboross
authored andcommitted
Add variance and generalizer tests
Added tests that verify that the generalizer works and outputs the correct constraints, and tests that verify variance is being handled correctly. Co-authored-by: David Ross <daboross@daboross.net>
1 parent 3f0f85f commit ecf20dc

File tree

1 file changed

+189
-4
lines changed

1 file changed

+189
-4
lines changed

tests/test/subtype.rs

Lines changed: 189 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,49 @@ fn ref_lifetime_variance() {
7272
}
7373

7474
#[test]
75-
fn fn_lifetime_variance() {
75+
fn fn_lifetime_variance_args() {
7676
test! {
7777
program {
7878
}
7979

8080
goal {
81-
Subtype(for<'a, 'b> fn(&'a u32, &'b u32), for<'a> fn(&'a u32, &'a u32))
81+
for<'a, 'b> fn(&'a u32, &'b u32) = for<'a> fn(&'a u32, &'a u32)
8282
} yields {
83+
"Unique;substitution [], lifetime constraints [\
84+
InEnvironment { environment: Env([]), goal: '!1_0: '!1_1 }, \
85+
InEnvironment { environment: Env([]), goal: '!1_1: '!1_0 }]"
86+
}
87+
}
88+
}
89+
90+
#[test]
91+
fn fn_lifetime_variance_with_return_type() {
92+
test! {
93+
program {
94+
}
95+
96+
goal {
97+
Subtype(for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32, for<'a> fn(&'a u32, &'a u32) -> &'a u32)
98+
} yields {
99+
// TODO: are these results actually correct?
83100
"Unique; for<?U1,?U1> { substitution [], lifetime constraints [\
84-
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
85-
InEnvironment { environment: Env([]), goal: '!1_0: '^0.1 }] }"
101+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
102+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.1 }, \
103+
InEnvironment { environment: Env([]), goal: '^0.0: '!1_0 } \
104+
]}"
105+
}
106+
goal {
107+
Subtype(for<'a> fn(&'a u32, &'a u32) -> &'a u32, for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32)
108+
} yields {
109+
"Unique; for<?U1> { substitution [], lifetime constraints [\
110+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
111+
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }, \
112+
InEnvironment { environment: Env([]), goal: '^0.0: '!1_0 } \
113+
] }"
86114
}
87115
}
88116
}
117+
89118
#[test]
90119
fn generalize() {
91120
test! {
@@ -108,6 +137,8 @@ fn generalize() {
108137
}
109138
}
110139

140+
/// Tests that the generalizer correctly generalizes lifetimes (as opposed to
141+
/// just that variance in general works).
111142
#[test]
112143
fn multi_lifetime() {
113144
test! {
@@ -121,6 +152,160 @@ fn multi_lifetime() {
121152
}
122153
}
123154
} yields {
155+
// Without the generalizer, we would yield a result like this:
156+
//
157+
// "Unique; substitution [?0 := (&'!1_1 Uint(U32))], lifetime
158+
// constraints [InEnvironment { environment: Env([]), goal: '!1_1: '!1_0
159+
// }]"
160+
//
161+
// This is incorrect, as we shouldn't be requiring 'a and 'b to be
162+
// related to eachother. Instead, U should be &'?1 u32, with constraints
163+
// ?1 : 'a, ?1: 'b.
164+
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
165+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
166+
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }] }"
167+
}
168+
}
169+
}
170+
171+
/// Tests that the generalizer generalizes lifetimes within a covariant struct.
172+
#[test]
173+
fn multi_lifetime_covariant_struct() {
174+
test! {
175+
program {
176+
#[variance(Covariant)]
177+
struct Foo<A> {}
178+
}
179+
180+
goal {
181+
forall<'a, 'b> {
182+
exists<U> {
183+
Subtype(Foo<&'a u32>, Foo<U>),
184+
Subtype(Foo<&'b u32>, Foo<U>)
185+
}
186+
}
187+
} yields {
188+
// Result should be identical to multi_lifetime result.
189+
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
190+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
191+
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }] }"
192+
}
193+
}
194+
}
195+
196+
/// Tests that the generalizer generalizes lifetimes within a contravariant
197+
/// struct, and that that variance contravariance is recognized.
198+
#[test]
199+
fn multi_lifetime_contravariant_struct() {
200+
test! {
201+
program {
202+
#[variance(Contravariant)]
203+
struct Foo<A> {}
204+
}
205+
206+
goal {
207+
forall<'a, 'b> {
208+
exists<U> {
209+
Subtype(Foo<&'a u32>, Foo<U>),
210+
Subtype(Foo<&'b u32>, Foo<U>)
211+
}
212+
}
213+
} yields {
214+
// Result should be opposite multi_lifetime result.
215+
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
216+
InEnvironment { environment: Env([]), goal: '^0.0: '!1_0 }, \
217+
InEnvironment { environment: Env([]), goal: '^0.0: '!1_1 }] }"
218+
}
219+
}
220+
}
221+
222+
/// Tests that the generalizer generalizes lifetimes within a invariant struct.
223+
#[test]
224+
fn multi_lifetime_invariant_struct() {
225+
test! {
226+
program {
227+
#[variance(Invariant)]
228+
struct Foo<A> {}
229+
}
230+
231+
goal {
232+
forall<'a, 'b> {
233+
exists<U> {
234+
Subtype(Foo<&'a u32>, Foo<U>),
235+
Subtype(Foo<&'b u32>, Foo<U>)
236+
}
237+
}
238+
} yields {
239+
// Because A is invariant, we require the lifetimes to be equal
240+
"Unique; substitution [?0 := (&'!1_1 Uint(U32))], lifetime
241+
constraints [InEnvironment { environment: Env([]), goal: '!1_0: '!1_1 }, \
242+
InEnvironment { environment: Env([]), goal: '!1_1: '!1_0 }]"
243+
}
244+
}
245+
}
246+
247+
/// Tests that the generalizer generalizes lifetimes within slices correctly.
248+
#[test]
249+
fn multi_lifetime_slice() {
250+
test! {
251+
program {
252+
}
253+
254+
goal {
255+
forall<'a, 'b> {
256+
exists<U> {
257+
Subtype([&'a u32], [U]),
258+
Subtype([&'b u32], [U])
259+
}
260+
}
261+
} yields {
262+
// Result should be identical to multi_lifetime result.
263+
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
264+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
265+
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }] }"
266+
}
267+
}
268+
}
269+
270+
/// Tests that the generalizer generalizes lifetimes within tuples correctly.
271+
#[test]
272+
fn multi_lifetime_tuple() {
273+
test! {
274+
program {
275+
}
276+
277+
goal {
278+
forall<'a, 'b> {
279+
exists<U> {
280+
Subtype((&'a u32, &'a u32), [U]),
281+
Subtype((&'b u32, &'b u32), [U])
282+
}
283+
}
284+
} yields {
285+
// Result should be identical to multi_lifetime result.
286+
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
287+
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
288+
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }] }"
289+
}
290+
}
291+
}
292+
293+
/// Tests that the generalizer generalizes lifetimes within tuples correctly.
294+
#[test]
295+
fn multi_lifetime_array() {
296+
test! {
297+
program {
298+
}
299+
300+
goal {
301+
forall<'a, 'b> {
302+
exists<U> {
303+
Subtype([&'a u32; 16], [U]),
304+
Subtype([&'b u32; 16], [U])
305+
}
306+
}
307+
} yields {
308+
// Result should be identical to multi_lifetime result.
124309
"Unique; for<?U1> { substitution [?0 := (&'^0.0 Uint(U32))], lifetime constraints [\
125310
InEnvironment { environment: Env([]), goal: '!1_0: '^0.0 }, \
126311
InEnvironment { environment: Env([]), goal: '!1_1: '^0.0 }] }"

0 commit comments

Comments
 (0)