]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir_ty/src/tests/coercion.rs
793c23e41c64f725dc6658fda506f374b571d259
[rust.git] / crates / ra_hir_ty / src / tests / coercion.rs
1 use super::infer_with_mismatches;
2 use insta::assert_snapshot;
3 use test_utils::covers;
4
5 // Infer with some common definitions and impls.
6 fn infer(source: &str) -> String {
7     let defs = r#"
8         #[lang = "sized"]
9         pub trait Sized {}
10         #[lang = "unsize"]
11         pub trait Unsize<T: ?Sized> {}
12         #[lang = "coerce_unsized"]
13         pub trait CoerceUnsized<T> {}
14
15         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
16         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
17     "#;
18
19     // Append to the end to keep positions unchanged.
20     super::infer(&format!("{}{}", source, defs))
21 }
22
23 #[test]
24 fn infer_block_expr_type_mismatch() {
25     assert_snapshot!(
26         infer(r#"
27 fn test() {
28     let a: i32 = { 1i64 };
29 }
30 "#),
31         @r###"
32     [11; 41) '{     ...4 }; }': ()
33     [21; 22) 'a': i32
34     [30; 38) '{ 1i64 }': i64
35     [32; 36) '1i64': i64
36     "###);
37 }
38
39 #[test]
40 fn coerce_places() {
41     assert_snapshot!(
42         infer(r#"
43 struct S<T> { a: T }
44
45 fn f<T>(_: &[T]) -> T { loop {} }
46 fn g<T>(_: S<&[T]>) -> T { loop {} }
47
48 fn gen<T>() -> *mut [T; 2] { loop {} }
49 fn test1<U>() -> *mut [U] {
50     gen()
51 }
52
53 fn test2() {
54     let arr: &[u8; 1] = &[1];
55
56     let a: &[_] = arr;
57     let b = f(arr);
58     let c: &[_] = { arr };
59     let d = g(S { a: arr });
60     let e: [&[_]; 1] = [arr];
61     let f: [&[_]; 2] = [arr; 2];
62     let g: (&[_], &[_]) = (arr, arr);
63 }
64 "#),
65         @r###"
66     [31; 32) '_': &[T]
67     [45; 56) '{ loop {} }': T
68     [47; 54) 'loop {}': !
69     [52; 54) '{}': ()
70     [65; 66) '_': S<&[T]>
71     [82; 93) '{ loop {} }': T
72     [84; 91) 'loop {}': !
73     [89; 91) '{}': ()
74     [122; 133) '{ loop {} }': *mut [T;_]
75     [124; 131) 'loop {}': !
76     [129; 131) '{}': ()
77     [160; 173) '{     gen() }': *mut [U]
78     [166; 169) 'gen': fn gen<U>() -> *mut [T;_]
79     [166; 171) 'gen()': *mut [U;_]
80     [186; 420) '{     ...rr); }': ()
81     [196; 199) 'arr': &[u8;_]
82     [212; 216) '&[1]': &[u8;_]
83     [213; 216) '[1]': [u8;_]
84     [214; 215) '1': u8
85     [227; 228) 'a': &[u8]
86     [237; 240) 'arr': &[u8;_]
87     [250; 251) 'b': u8
88     [254; 255) 'f': fn f<u8>(&[T]) -> T
89     [254; 260) 'f(arr)': u8
90     [256; 259) 'arr': &[u8;_]
91     [270; 271) 'c': &[u8]
92     [280; 287) '{ arr }': &[u8]
93     [282; 285) 'arr': &[u8;_]
94     [297; 298) 'd': u8
95     [301; 302) 'g': fn g<u8>(S<&[T]>) -> T
96     [301; 316) 'g(S { a: arr })': u8
97     [303; 315) 'S { a: arr }': S<&[u8]>
98     [310; 313) 'arr': &[u8;_]
99     [326; 327) 'e': [&[u8];_]
100     [341; 346) '[arr]': [&[u8];_]
101     [342; 345) 'arr': &[u8;_]
102     [356; 357) 'f': [&[u8];_]
103     [371; 379) '[arr; 2]': [&[u8];_]
104     [372; 375) 'arr': &[u8;_]
105     [377; 378) '2': usize
106     [389; 390) 'g': (&[u8], &[u8])
107     [407; 417) '(arr, arr)': (&[u8], &[u8])
108     [408; 411) 'arr': &[u8;_]
109     [413; 416) 'arr': &[u8;_]
110     "###
111     );
112 }
113
114 #[test]
115 fn infer_let_stmt_coerce() {
116     assert_snapshot!(
117         infer(r#"
118 fn test() {
119     let x: &[i32] = &[1];
120 }
121 "#),
122         @r###"
123     [11; 40) '{     ...[1]; }': ()
124     [21; 22) 'x': &[i32]
125     [33; 37) '&[1]': &[i32;_]
126     [34; 37) '[1]': [i32;_]
127     [35; 36) '1': i32
128     "###);
129 }
130
131 #[test]
132 fn infer_custom_coerce_unsized() {
133     assert_snapshot!(
134         infer(r#"
135 struct A<T: ?Sized>(*const T);
136 struct B<T: ?Sized>(*const T);
137 struct C<T: ?Sized> { inner: *const T }
138
139 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
140 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
141
142 fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
143 fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
144 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
145
146 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
147     let d = foo1(a);
148     let e = foo2(b);
149     let f = foo3(c);
150 }
151 "#),
152         @r###"
153     [258; 259) 'x': A<[T]>
154     [279; 284) '{ x }': A<[T]>
155     [281; 282) 'x': A<[T]>
156     [296; 297) 'x': B<[T]>
157     [317; 322) '{ x }': B<[T]>
158     [319; 320) 'x': B<[T]>
159     [334; 335) 'x': C<[T]>
160     [355; 360) '{ x }': C<[T]>
161     [357; 358) 'x': C<[T]>
162     [370; 371) 'a': A<[u8;_]>
163     [385; 386) 'b': B<[u8;_]>
164     [400; 401) 'c': C<[u8;_]>
165     [415; 481) '{     ...(c); }': ()
166     [425; 426) 'd': A<[{unknown}]>
167     [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]>
168     [429; 436) 'foo1(a)': A<[{unknown}]>
169     [434; 435) 'a': A<[u8;_]>
170     [446; 447) 'e': B<[u8]>
171     [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]>
172     [450; 457) 'foo2(b)': B<[u8]>
173     [455; 456) 'b': B<[u8;_]>
174     [467; 468) 'f': C<[u8]>
175     [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]>
176     [471; 478) 'foo3(c)': C<[u8]>
177     [476; 477) 'c': C<[u8;_]>
178     "###
179     );
180 }
181
182 #[test]
183 fn infer_if_coerce() {
184     assert_snapshot!(
185         infer(r#"
186 fn foo<T>(x: &[T]) -> &[T] { loop {} }
187 fn test() {
188     let x = if true {
189         foo(&[1])
190     } else {
191         &[1]
192     };
193 }
194 "#),
195         @r###"
196     [11; 12) 'x': &[T]
197     [28; 39) '{ loop {} }': &[T]
198     [30; 37) 'loop {}': !
199     [35; 37) '{}': ()
200     [50; 126) '{     ...  }; }': ()
201     [60; 61) 'x': &[i32]
202     [64; 123) 'if tru...     }': &[i32]
203     [67; 71) 'true': bool
204     [72; 97) '{     ...     }': &[i32]
205     [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T]
206     [82; 91) 'foo(&[1])': &[i32]
207     [86; 90) '&[1]': &[i32;_]
208     [87; 90) '[1]': [i32;_]
209     [88; 89) '1': i32
210     [103; 123) '{     ...     }': &[i32;_]
211     [113; 117) '&[1]': &[i32;_]
212     [114; 117) '[1]': [i32;_]
213     [115; 116) '1': i32
214     "###
215     );
216 }
217
218 #[test]
219 fn infer_if_else_coerce() {
220     assert_snapshot!(
221         infer(r#"
222 fn foo<T>(x: &[T]) -> &[T] { loop {} }
223 fn test() {
224     let x = if true {
225         &[1]
226     } else {
227         foo(&[1])
228     };
229 }
230 "#),
231         @r###"
232     [11; 12) 'x': &[T]
233     [28; 39) '{ loop {} }': &[T]
234     [30; 37) 'loop {}': !
235     [35; 37) '{}': ()
236     [50; 126) '{     ...  }; }': ()
237     [60; 61) 'x': &[i32]
238     [64; 123) 'if tru...     }': &[i32]
239     [67; 71) 'true': bool
240     [72; 92) '{     ...     }': &[i32;_]
241     [82; 86) '&[1]': &[i32;_]
242     [83; 86) '[1]': [i32;_]
243     [84; 85) '1': i32
244     [98; 123) '{     ...     }': &[i32]
245     [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T]
246     [108; 117) 'foo(&[1])': &[i32]
247     [112; 116) '&[1]': &[i32;_]
248     [113; 116) '[1]': [i32;_]
249     [114; 115) '1': i32
250     "###
251     );
252 }
253
254 #[test]
255 fn infer_match_first_coerce() {
256     assert_snapshot!(
257         infer(r#"
258 fn foo<T>(x: &[T]) -> &[T] { loop {} }
259 fn test(i: i32) {
260     let x = match i {
261         2 => foo(&[2]),
262         1 => &[1],
263         _ => &[3],
264     };
265 }
266 "#),
267         @r###"
268     [11; 12) 'x': &[T]
269     [28; 39) '{ loop {} }': &[T]
270     [30; 37) 'loop {}': !
271     [35; 37) '{}': ()
272     [48; 49) 'i': i32
273     [56; 150) '{     ...  }; }': ()
274     [66; 67) 'x': &[i32]
275     [70; 147) 'match ...     }': &[i32]
276     [76; 77) 'i': i32
277     [88; 89) '2': i32
278     [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T]
279     [93; 102) 'foo(&[2])': &[i32]
280     [97; 101) '&[2]': &[i32;_]
281     [98; 101) '[2]': [i32;_]
282     [99; 100) '2': i32
283     [112; 113) '1': i32
284     [117; 121) '&[1]': &[i32;_]
285     [118; 121) '[1]': [i32;_]
286     [119; 120) '1': i32
287     [131; 132) '_': i32
288     [136; 140) '&[3]': &[i32;_]
289     [137; 140) '[3]': [i32;_]
290     [138; 139) '3': i32
291     "###
292     );
293 }
294
295 #[test]
296 fn infer_match_second_coerce() {
297     assert_snapshot!(
298         infer(r#"
299 fn foo<T>(x: &[T]) -> &[T] { loop {} }
300 fn test(i: i32) {
301     let x = match i {
302         1 => &[1],
303         2 => foo(&[2]),
304         _ => &[3],
305     };
306 }
307 "#),
308         @r###"
309     [11; 12) 'x': &[T]
310     [28; 39) '{ loop {} }': &[T]
311     [30; 37) 'loop {}': !
312     [35; 37) '{}': ()
313     [48; 49) 'i': i32
314     [56; 150) '{     ...  }; }': ()
315     [66; 67) 'x': &[i32]
316     [70; 147) 'match ...     }': &[i32]
317     [76; 77) 'i': i32
318     [88; 89) '1': i32
319     [93; 97) '&[1]': &[i32;_]
320     [94; 97) '[1]': [i32;_]
321     [95; 96) '1': i32
322     [107; 108) '2': i32
323     [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T]
324     [112; 121) 'foo(&[2])': &[i32]
325     [116; 120) '&[2]': &[i32;_]
326     [117; 120) '[2]': [i32;_]
327     [118; 119) '2': i32
328     [131; 132) '_': i32
329     [136; 140) '&[3]': &[i32;_]
330     [137; 140) '[3]': [i32;_]
331     [138; 139) '3': i32
332     "###
333     );
334 }
335
336 #[test]
337 fn coerce_merge_one_by_one1() {
338     covers!(coerce_merge_fail_fallback);
339
340     assert_snapshot!(
341         infer(r#"
342 fn test() {
343     let t = &mut 1;
344     let x = match 1 {
345         1 => t as *mut i32,
346         2 => t as &i32,
347         _ => t as *const i32,
348     };
349 }
350 "#),
351         @r###"
352     [11; 145) '{     ...  }; }': ()
353     [21; 22) 't': &mut i32
354     [25; 31) '&mut 1': &mut i32
355     [30; 31) '1': i32
356     [41; 42) 'x': *const i32
357     [45; 142) 'match ...     }': *const i32
358     [51; 52) '1': i32
359     [63; 64) '1': i32
360     [68; 69) 't': &mut i32
361     [68; 81) 't as *mut i32': *mut i32
362     [91; 92) '2': i32
363     [96; 97) 't': &mut i32
364     [96; 105) 't as &i32': &i32
365     [115; 116) '_': i32
366     [120; 121) 't': &mut i32
367     [120; 135) 't as *const i32': *const i32
368     "###
369     );
370 }
371
372 #[test]
373 fn return_coerce_unknown() {
374     assert_snapshot!(
375         infer_with_mismatches(r#"
376 fn foo() -> u32 {
377     return unknown;
378 }
379 "#, true),
380         @r###"
381     [17; 40) '{     ...own; }': !
382     [23; 37) 'return unknown': !
383     [30; 37) 'unknown': u32
384     "###
385     );
386 }
387
388 #[test]
389 fn coerce_autoderef() {
390     assert_snapshot!(
391         infer_with_mismatches(r#"
392 struct Foo;
393 fn takes_ref_foo(x: &Foo) {}
394 fn test() {
395     takes_ref_foo(&Foo);
396     takes_ref_foo(&&Foo);
397     takes_ref_foo(&&&Foo);
398 }
399 "#, true),
400         @r###"
401     [30; 31) 'x': &Foo
402     [39; 41) '{}': ()
403     [52; 133) '{     ...oo); }': ()
404     [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
405     [58; 77) 'takes_...(&Foo)': ()
406     [72; 76) '&Foo': &Foo
407     [73; 76) 'Foo': Foo
408     [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
409     [83; 103) 'takes_...&&Foo)': ()
410     [97; 102) '&&Foo': &&Foo
411     [98; 102) '&Foo': &Foo
412     [99; 102) 'Foo': Foo
413     [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> ()
414     [109; 130) 'takes_...&&Foo)': ()
415     [123; 129) '&&&Foo': &&&Foo
416     [124; 129) '&&Foo': &&Foo
417     [125; 129) '&Foo': &Foo
418     [126; 129) 'Foo': Foo
419     "###
420     );
421 }
422
423 #[test]
424 fn coerce_autoderef_generic() {
425     assert_snapshot!(
426         infer_with_mismatches(r#"
427 struct Foo;
428 fn takes_ref<T>(x: &T) -> T { *x }
429 fn test() {
430     takes_ref(&Foo);
431     takes_ref(&&Foo);
432     takes_ref(&&&Foo);
433 }
434 "#, true),
435         @r###"
436     [29; 30) 'x': &T
437     [41; 47) '{ *x }': T
438     [43; 45) '*x': T
439     [44; 45) 'x': &T
440     [58; 127) '{     ...oo); }': ()
441     [64; 73) 'takes_ref': fn takes_ref<Foo>(&T) -> T
442     [64; 79) 'takes_ref(&Foo)': Foo
443     [74; 78) '&Foo': &Foo
444     [75; 78) 'Foo': Foo
445     [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T
446     [85; 101) 'takes_...&&Foo)': &Foo
447     [95; 100) '&&Foo': &&Foo
448     [96; 100) '&Foo': &Foo
449     [97; 100) 'Foo': Foo
450     [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T
451     [107; 124) 'takes_...&&Foo)': &&Foo
452     [117; 123) '&&&Foo': &&&Foo
453     [118; 123) '&&Foo': &&Foo
454     [119; 123) '&Foo': &Foo
455     [120; 123) 'Foo': Foo
456     "###
457     );
458 }
459
460 #[test]
461 fn closure_return_coerce() {
462     assert_snapshot!(
463         infer_with_mismatches(r#"
464 fn foo() {
465     let x = || {
466         if true {
467             return &1u32;
468         }
469         &&1u32
470     };
471 }
472 "#, true),
473         @r###"
474     [10; 106) '{     ...  }; }': ()
475     [20; 21) 'x': || -> &u32
476     [24; 103) '|| {  ...     }': || -> &u32
477     [27; 103) '{     ...     }': &u32
478     [37; 82) 'if tru...     }': ()
479     [40; 44) 'true': bool
480     [45; 82) '{     ...     }': !
481     [59; 71) 'return &1u32': !
482     [66; 71) '&1u32': &u32
483     [67; 71) '1u32': u32
484     [91; 97) '&&1u32': &&u32
485     [92; 97) '&1u32': &u32
486     [93; 97) '1u32': u32
487     "###
488     );
489 }