]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/coercion.rs
internal: introduce minicore -- a subset of libcore for testing
[rust.git] / crates / hir_ty / src / tests / coercion.rs
1 use expect_test::expect;
2
3 use super::{check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};
4
5 #[test]
6 fn infer_block_expr_type_mismatch() {
7     check_infer(
8         r"
9         fn test() {
10             let a: i32 = { 1i64 };
11         }
12         ",
13         expect![[r"
14             10..40 '{     ...4 }; }': ()
15             20..21 'a': i32
16             29..37 '{ 1i64 }': i64
17             31..35 '1i64': i64
18         "]],
19     );
20 }
21
22 #[test]
23 fn coerce_places() {
24     check_infer(
25         r#"
26 //- minicore: coerce_unsized
27 struct S<T> { a: T }
28
29 fn f<T>(_: &[T]) -> T { loop {} }
30 fn g<T>(_: S<&[T]>) -> T { loop {} }
31
32 fn gen<T>() -> *mut [T; 2] { loop {} }
33 fn test1<U>() -> *mut [U] {
34     gen()
35 }
36
37 fn test2() {
38     let arr: &[u8; 1] = &[1];
39
40     let a: &[_] = arr;
41     let b = f(arr);
42     let c: &[_] = { arr };
43     let d = g(S { a: arr });
44     let e: [&[_]; 1] = [arr];
45     let f: [&[_]; 2] = [arr; 2];
46     let g: (&[_], &[_]) = (arr, arr);
47 }
48 "#,
49         expect![[r#"
50             30..31 '_': &[T]
51             44..55 '{ loop {} }': T
52             46..53 'loop {}': !
53             51..53 '{}': ()
54             64..65 '_': S<&[T]>
55             81..92 '{ loop {} }': T
56             83..90 'loop {}': !
57             88..90 '{}': ()
58             121..132 '{ loop {} }': *mut [T; 2]
59             123..130 'loop {}': !
60             128..130 '{}': ()
61             159..172 '{     gen() }': *mut [U]
62             165..168 'gen': fn gen<U>() -> *mut [U; 2]
63             165..170 'gen()': *mut [U; 2]
64             185..419 '{     ...rr); }': ()
65             195..198 'arr': &[u8; 1]
66             211..215 '&[1]': &[u8; 1]
67             212..215 '[1]': [u8; 1]
68             213..214 '1': u8
69             226..227 'a': &[u8]
70             236..239 'arr': &[u8; 1]
71             249..250 'b': u8
72             253..254 'f': fn f<u8>(&[u8]) -> u8
73             253..259 'f(arr)': u8
74             255..258 'arr': &[u8; 1]
75             269..270 'c': &[u8]
76             279..286 '{ arr }': &[u8]
77             281..284 'arr': &[u8; 1]
78             296..297 'd': u8
79             300..301 'g': fn g<u8>(S<&[u8]>) -> u8
80             300..315 'g(S { a: arr })': u8
81             302..314 'S { a: arr }': S<&[u8]>
82             309..312 'arr': &[u8; 1]
83             325..326 'e': [&[u8]; 1]
84             340..345 '[arr]': [&[u8]; 1]
85             341..344 'arr': &[u8; 1]
86             355..356 'f': [&[u8]; 2]
87             370..378 '[arr; 2]': [&[u8]; 2]
88             371..374 'arr': &[u8; 1]
89             376..377 '2': usize
90             388..389 'g': (&[u8], &[u8])
91             406..416 '(arr, arr)': (&[u8], &[u8])
92             407..410 'arr': &[u8; 1]
93             412..415 'arr': &[u8; 1]
94         "#]],
95     );
96 }
97
98 #[test]
99 fn infer_let_stmt_coerce() {
100     check_infer(
101         r"
102         fn test() {
103             let x: &[isize] = &[1];
104             let x: *const [isize] = &[1];
105         }
106         ",
107         expect![[r#"
108             10..75 '{     ...[1]; }': ()
109             20..21 'x': &[isize]
110             34..38 '&[1]': &[isize; 1]
111             35..38 '[1]': [isize; 1]
112             36..37 '1': isize
113             48..49 'x': *const [isize]
114             68..72 '&[1]': &[isize; 1]
115             69..72 '[1]': [isize; 1]
116             70..71 '1': isize
117         "#]],
118     );
119 }
120
121 #[test]
122 fn infer_custom_coerce_unsized() {
123     check_infer(
124         r#"
125         struct A<T: ?Sized>(*const T);
126         struct B<T: ?Sized>(*const T);
127         struct C<T: ?Sized> { inner: *const T }
128
129         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
130         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
131
132         fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
133         fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
134         fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
135
136         fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
137             let d = foo1(a);
138             let e = foo2(b);
139             let f = foo3(c);
140         }
141
142
143         #[lang = "sized"]
144         pub trait Sized {}
145         #[lang = "unsize"]
146         pub trait Unsize<T: ?Sized> {}
147         #[lang = "coerce_unsized"]
148         pub trait CoerceUnsized<T> {}
149
150         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
151         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
152         "#,
153         expect![[r#"
154             257..258 'x': A<[T]>
155             278..283 '{ x }': A<[T]>
156             280..281 'x': A<[T]>
157             295..296 'x': B<[T]>
158             316..321 '{ x }': B<[T]>
159             318..319 'x': B<[T]>
160             333..334 'x': C<[T]>
161             354..359 '{ x }': C<[T]>
162             356..357 'x': C<[T]>
163             369..370 'a': A<[u8; 2]>
164             384..385 'b': B<[u8; 2]>
165             399..400 'c': C<[u8; 2]>
166             414..480 '{     ...(c); }': ()
167             424..425 'd': A<[{unknown}]>
168             428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
169             428..435 'foo1(a)': A<[{unknown}]>
170             433..434 'a': A<[u8; 2]>
171             445..446 'e': B<[u8]>
172             449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
173             449..456 'foo2(b)': B<[u8]>
174             454..455 'b': B<[u8; 2]>
175             466..467 'f': C<[u8]>
176             470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
177             470..477 'foo3(c)': C<[u8]>
178             475..476 'c': C<[u8; 2]>
179         "#]],
180     );
181 }
182
183 #[test]
184 fn infer_if_coerce() {
185     check_infer(
186         r#"
187         fn foo<T>(x: &[T]) -> &[T] { loop {} }
188         fn test() {
189             let x = if true {
190                 foo(&[1])
191             } else {
192                 &[1]
193             };
194         }
195
196
197         #[lang = "sized"]
198         pub trait Sized {}
199         #[lang = "unsize"]
200         pub trait Unsize<T: ?Sized> {}
201         "#,
202         expect![[r#"
203             10..11 'x': &[T]
204             27..38 '{ loop {} }': &[T]
205             29..36 'loop {}': !
206             34..36 '{}': ()
207             49..125 '{     ...  }; }': ()
208             59..60 'x': &[i32]
209             63..122 'if tru...     }': &[i32]
210             66..70 'true': bool
211             71..96 '{     ...     }': &[i32]
212             81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
213             81..90 'foo(&[1])': &[i32]
214             85..89 '&[1]': &[i32; 1]
215             86..89 '[1]': [i32; 1]
216             87..88 '1': i32
217             102..122 '{     ...     }': &[i32; 1]
218             112..116 '&[1]': &[i32; 1]
219             113..116 '[1]': [i32; 1]
220             114..115 '1': i32
221         "#]],
222     );
223 }
224
225 #[test]
226 fn infer_if_else_coerce() {
227     check_infer(
228         r#"
229         fn foo<T>(x: &[T]) -> &[T] { loop {} }
230         fn test() {
231             let x = if true {
232                 &[1]
233             } else {
234                 foo(&[1])
235             };
236         }
237
238         #[lang = "sized"]
239         pub trait Sized {}
240         #[lang = "unsize"]
241         pub trait Unsize<T: ?Sized> {}
242         #[lang = "coerce_unsized"]
243         pub trait CoerceUnsized<T> {}
244
245         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
246         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
247         "#,
248         expect![[r#"
249             10..11 'x': &[T]
250             27..38 '{ loop {} }': &[T]
251             29..36 'loop {}': !
252             34..36 '{}': ()
253             49..125 '{     ...  }; }': ()
254             59..60 'x': &[i32]
255             63..122 'if tru...     }': &[i32]
256             66..70 'true': bool
257             71..91 '{     ...     }': &[i32; 1]
258             81..85 '&[1]': &[i32; 1]
259             82..85 '[1]': [i32; 1]
260             83..84 '1': i32
261             97..122 '{     ...     }': &[i32]
262             107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
263             107..116 'foo(&[1])': &[i32]
264             111..115 '&[1]': &[i32; 1]
265             112..115 '[1]': [i32; 1]
266             113..114 '1': i32
267         "#]],
268     )
269 }
270
271 #[test]
272 fn infer_match_first_coerce() {
273     check_infer(
274         r#"
275         fn foo<T>(x: &[T]) -> &[T] { loop {} }
276         fn test(i: i32) {
277             let x = match i {
278                 2 => foo(&[2]),
279                 1 => &[1],
280                 _ => &[3],
281             };
282         }
283
284         #[lang = "sized"]
285         pub trait Sized {}
286         #[lang = "unsize"]
287         pub trait Unsize<T: ?Sized> {}
288         "#,
289         expect![[r#"
290             10..11 'x': &[T]
291             27..38 '{ loop {} }': &[T]
292             29..36 'loop {}': !
293             34..36 '{}': ()
294             47..48 'i': i32
295             55..149 '{     ...  }; }': ()
296             65..66 'x': &[i32]
297             69..146 'match ...     }': &[i32]
298             75..76 'i': i32
299             87..88 '2': i32
300             87..88 '2': i32
301             92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
302             92..101 'foo(&[2])': &[i32]
303             96..100 '&[2]': &[i32; 1]
304             97..100 '[2]': [i32; 1]
305             98..99 '2': i32
306             111..112 '1': i32
307             111..112 '1': i32
308             116..120 '&[1]': &[i32; 1]
309             117..120 '[1]': [i32; 1]
310             118..119 '1': i32
311             130..131 '_': i32
312             135..139 '&[3]': &[i32; 1]
313             136..139 '[3]': [i32; 1]
314             137..138 '3': i32
315         "#]],
316     );
317 }
318
319 #[test]
320 fn infer_match_second_coerce() {
321     check_infer(
322         r#"
323         fn foo<T>(x: &[T]) -> &[T] { loop {} }
324         fn test(i: i32) {
325             let x = match i {
326                 1 => &[1],
327                 2 => foo(&[2]),
328                 _ => &[3],
329             };
330         }
331
332         #[lang = "sized"]
333         pub trait Sized {}
334         #[lang = "unsize"]
335         pub trait Unsize<T: ?Sized> {}
336         #[lang = "coerce_unsized"]
337         pub trait CoerceUnsized<T> {}
338
339         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
340         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
341         "#,
342         expect![[r#"
343             10..11 'x': &[T]
344             27..38 '{ loop {} }': &[T]
345             29..36 'loop {}': !
346             34..36 '{}': ()
347             47..48 'i': i32
348             55..149 '{     ...  }; }': ()
349             65..66 'x': &[i32]
350             69..146 'match ...     }': &[i32]
351             75..76 'i': i32
352             87..88 '1': i32
353             87..88 '1': i32
354             92..96 '&[1]': &[i32; 1]
355             93..96 '[1]': [i32; 1]
356             94..95 '1': i32
357             106..107 '2': i32
358             106..107 '2': i32
359             111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
360             111..120 'foo(&[2])': &[i32]
361             115..119 '&[2]': &[i32; 1]
362             116..119 '[2]': [i32; 1]
363             117..118 '2': i32
364             130..131 '_': i32
365             135..139 '&[3]': &[i32; 1]
366             136..139 '[3]': [i32; 1]
367             137..138 '3': i32
368         "#]],
369     );
370 }
371
372 #[test]
373 fn coerce_merge_one_by_one1() {
374     cov_mark::check!(coerce_merge_fail_fallback);
375
376     check_infer(
377         r"
378         fn test() {
379             let t = &mut 1;
380             let x = match 1 {
381                 1 => t as *mut i32,
382                 2 => t as &i32,
383                 _ => t as *const i32,
384             };
385         }
386         ",
387         expect![[r"
388             10..144 '{     ...  }; }': ()
389             20..21 't': &mut i32
390             24..30 '&mut 1': &mut i32
391             29..30 '1': i32
392             40..41 'x': *const i32
393             44..141 'match ...     }': *const i32
394             50..51 '1': i32
395             62..63 '1': i32
396             62..63 '1': i32
397             67..68 't': &mut i32
398             67..80 't as *mut i32': *mut i32
399             90..91 '2': i32
400             90..91 '2': i32
401             95..96 't': &mut i32
402             95..104 't as &i32': &i32
403             114..115 '_': i32
404             119..120 't': &mut i32
405             119..134 't as *const i32': *const i32
406     "]],
407     );
408 }
409
410 #[test]
411 fn return_coerce_unknown() {
412     check_infer_with_mismatches(
413         r"
414         fn foo() -> u32 {
415             return unknown;
416         }
417         ",
418         expect![[r"
419             16..39 '{     ...own; }': u32
420             22..36 'return unknown': !
421             29..36 'unknown': u32
422         "]],
423     );
424 }
425
426 #[test]
427 fn coerce_autoderef() {
428     check_infer_with_mismatches(
429         r"
430         struct Foo;
431         fn takes_ref_foo(x: &Foo) {}
432         fn test() {
433             takes_ref_foo(&Foo);
434             takes_ref_foo(&&Foo);
435             takes_ref_foo(&&&Foo);
436         }
437         ",
438         expect![[r"
439             29..30 'x': &Foo
440             38..40 '{}': ()
441             51..132 '{     ...oo); }': ()
442             57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
443             57..76 'takes_...(&Foo)': ()
444             71..75 '&Foo': &Foo
445             72..75 'Foo': Foo
446             82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
447             82..102 'takes_...&&Foo)': ()
448             96..101 '&&Foo': &&Foo
449             97..101 '&Foo': &Foo
450             98..101 'Foo': Foo
451             108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
452             108..129 'takes_...&&Foo)': ()
453             122..128 '&&&Foo': &&&Foo
454             123..128 '&&Foo': &&Foo
455             124..128 '&Foo': &Foo
456             125..128 'Foo': Foo
457         "]],
458     );
459 }
460
461 #[test]
462 fn coerce_autoderef_generic() {
463     check_infer_with_mismatches(
464         r"
465         struct Foo;
466         fn takes_ref<T>(x: &T) -> T { *x }
467         fn test() {
468             takes_ref(&Foo);
469             takes_ref(&&Foo);
470             takes_ref(&&&Foo);
471         }
472         ",
473         expect![[r"
474             28..29 'x': &T
475             40..46 '{ *x }': T
476             42..44 '*x': T
477             43..44 'x': &T
478             57..126 '{     ...oo); }': ()
479             63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
480             63..78 'takes_ref(&Foo)': Foo
481             73..77 '&Foo': &Foo
482             74..77 'Foo': Foo
483             84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
484             84..100 'takes_...&&Foo)': &Foo
485             94..99 '&&Foo': &&Foo
486             95..99 '&Foo': &Foo
487             96..99 'Foo': Foo
488             106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
489             106..123 'takes_...&&Foo)': &&Foo
490             116..122 '&&&Foo': &&&Foo
491             117..122 '&&Foo': &&Foo
492             118..122 '&Foo': &Foo
493             119..122 'Foo': Foo
494         "]],
495     );
496 }
497
498 #[test]
499 fn coerce_autoderef_block() {
500     check_infer_with_mismatches(
501         r#"
502         struct String {}
503         #[lang = "deref"]
504         trait Deref { type Target; }
505         impl Deref for String { type Target = str; }
506         fn takes_ref_str(x: &str) {}
507         fn returns_string() -> String { loop {} }
508         fn test() {
509             takes_ref_str(&{ returns_string() });
510         }
511         "#,
512         expect![[r"
513             126..127 'x': &str
514             135..137 '{}': ()
515             168..179 '{ loop {} }': String
516             170..177 'loop {}': !
517             175..177 '{}': ()
518             190..235 '{     ... }); }': ()
519             196..209 'takes_ref_str': fn takes_ref_str(&str)
520             196..232 'takes_...g() })': ()
521             210..231 '&{ ret...ng() }': &String
522             211..231 '{ retu...ng() }': String
523             213..227 'returns_string': fn returns_string() -> String
524             213..229 'return...ring()': String
525         "]],
526     );
527 }
528
529 #[test]
530 fn closure_return_coerce() {
531     check_infer_with_mismatches(
532         r"
533         fn foo() {
534             let x = || {
535                 if true {
536                     return &1u32;
537                 }
538                 &&1u32
539             };
540         }
541         ",
542         expect![[r"
543             9..105 '{     ...  }; }': ()
544             19..20 'x': || -> &u32
545             23..102 '|| {  ...     }': || -> &u32
546             26..102 '{     ...     }': &u32
547             36..81 'if tru...     }': ()
548             39..43 'true': bool
549             44..81 '{     ...     }': ()
550             58..70 'return &1u32': !
551             65..70 '&1u32': &u32
552             66..70 '1u32': u32
553             90..96 '&&1u32': &&u32
554             91..96 '&1u32': &u32
555             92..96 '1u32': u32
556         "]],
557     );
558 }
559
560 #[test]
561 fn coerce_fn_item_to_fn_ptr() {
562     check_infer_with_mismatches(
563         r"
564         fn foo(x: u32) -> isize { 1 }
565         fn test() {
566             let f: fn(u32) -> isize = foo;
567         }
568         ",
569         expect![[r"
570             7..8 'x': u32
571             24..29 '{ 1 }': isize
572             26..27 '1': isize
573             40..78 '{     ...foo; }': ()
574             50..51 'f': fn(u32) -> isize
575             72..75 'foo': fn foo(u32) -> isize
576         "]],
577     );
578 }
579
580 #[test]
581 fn coerce_fn_items_in_match_arms() {
582     cov_mark::check!(coerce_fn_reification);
583
584     check_infer_with_mismatches(
585         r"
586         fn foo1(x: u32) -> isize { 1 }
587         fn foo2(x: u32) -> isize { 2 }
588         fn foo3(x: u32) -> isize { 3 }
589         fn test() {
590             let x = match 1 {
591                 1 => foo1,
592                 2 => foo2,
593                 _ => foo3,
594             };
595         }
596         ",
597         expect![[r"
598             8..9 'x': u32
599             25..30 '{ 1 }': isize
600             27..28 '1': isize
601             39..40 'x': u32
602             56..61 '{ 2 }': isize
603             58..59 '2': isize
604             70..71 'x': u32
605             87..92 '{ 3 }': isize
606             89..90 '3': isize
607             103..192 '{     ...  }; }': ()
608             113..114 'x': fn(u32) -> isize
609             117..189 'match ...     }': fn(u32) -> isize
610             123..124 '1': i32
611             135..136 '1': i32
612             135..136 '1': i32
613             140..144 'foo1': fn foo1(u32) -> isize
614             154..155 '2': i32
615             154..155 '2': i32
616             159..163 'foo2': fn foo2(u32) -> isize
617             173..174 '_': i32
618             178..182 'foo3': fn foo3(u32) -> isize
619         "]],
620     );
621 }
622
623 #[test]
624 fn coerce_closure_to_fn_ptr() {
625     check_infer_with_mismatches(
626         r"
627         fn test() {
628             let f: fn(u32) -> isize = |x| { 1 };
629         }
630         ",
631         expect![[r"
632             10..54 '{     ...1 }; }': ()
633             20..21 'f': fn(u32) -> isize
634             42..51 '|x| { 1 }': |u32| -> isize
635             43..44 'x': u32
636             46..51 '{ 1 }': isize
637             48..49 '1': isize
638         "]],
639     );
640 }
641
642 #[test]
643 fn coerce_placeholder_ref() {
644     // placeholders should unify, even behind references
645     check_infer_with_mismatches(
646         r"
647         struct S<T> { t: T }
648         impl<TT> S<TT> {
649             fn get(&self) -> &TT {
650                 &self.t
651             }
652         }
653         ",
654         expect![[r"
655             50..54 'self': &S<TT>
656             63..86 '{     ...     }': &TT
657             73..80 '&self.t': &TT
658             74..78 'self': &S<TT>
659             74..80 'self.t': TT
660         "]],
661     );
662 }
663
664 #[test]
665 fn coerce_unsize_array() {
666     check_infer_with_mismatches(
667         r#"
668         #[lang = "unsize"]
669         pub trait Unsize<T> {}
670         #[lang = "coerce_unsized"]
671         pub trait CoerceUnsized<T> {}
672
673         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
674
675         fn test() {
676             let f: &[usize] = &[1, 2, 3];
677         }
678         "#,
679         expect![[r#"
680             161..198 '{     ... 3]; }': ()
681             171..172 'f': &[usize]
682             185..195 '&[1, 2, 3]': &[usize; 3]
683             186..195 '[1, 2, 3]': [usize; 3]
684             187..188 '1': usize
685             190..191 '2': usize
686             193..194 '3': usize
687         "#]],
688     );
689 }
690
691 #[test]
692 fn coerce_unsize_trait_object_simple() {
693     check_infer_with_mismatches(
694         r#"
695         #[lang = "sized"]
696         pub trait Sized {}
697         #[lang = "unsize"]
698         pub trait Unsize<T> {}
699         #[lang = "coerce_unsized"]
700         pub trait CoerceUnsized<T> {}
701
702         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
703
704         trait Foo<T, U> {}
705         trait Bar<U, T, X>: Foo<T, U> {}
706         trait Baz<T, X>: Bar<usize, T, X> {}
707
708         struct S<T, X>;
709         impl<T, X> Foo<T, usize> for S<T, X> {}
710         impl<T, X> Bar<usize, T, X> for S<T, X> {}
711         impl<T, X> Baz<T, X> for S<T, X> {}
712
713         fn test() {
714             let obj: &dyn Baz<i8, i16> = &S;
715             let obj: &dyn Bar<_, i8, i16> = &S;
716             let obj: &dyn Foo<i8, _> = &S;
717         }
718         "#,
719         expect![[r"
720             424..539 '{     ... &S; }': ()
721             434..437 'obj': &dyn Baz<i8, i16>
722             459..461 '&S': &S<i8, i16>
723             460..461 'S': S<i8, i16>
724             471..474 'obj': &dyn Bar<usize, i8, i16>
725             499..501 '&S': &S<i8, i16>
726             500..501 'S': S<i8, i16>
727             511..514 'obj': &dyn Foo<i8, usize>
728             534..536 '&S': &S<i8, {unknown}>
729             535..536 'S': S<i8, {unknown}>
730         "]],
731     );
732 }
733
734 #[test]
735 fn coerce_unsize_trait_object_to_trait_object() {
736     // FIXME: The rust reference says this should be possible, but rustc doesn't
737     // implement it. We used to support it, but Chalk doesn't. Here's the
738     // correct expect:
739     //
740     //     424..609 '{     ...bj2; }': ()
741     //     434..437 'obj': &dyn Baz<i8, i16>
742     //     459..461 '&S': &S<i8, i16>
743     //     460..461 'S': S<i8, i16>
744     //     471..474 'obj': &dyn Bar<usize, i8, i16>
745     //     496..499 'obj': &dyn Baz<i8, i16>
746     //     509..512 'obj': &dyn Foo<i8, usize>
747     //     531..534 'obj': &dyn Bar<usize, i8, i16>
748     //     544..548 'obj2': &dyn Baz<i8, i16>
749     //     570..572 '&S': &S<i8, i16>
750     //     571..572 'S': S<i8, i16>
751     //     582..583 '_': &dyn Foo<i8, usize>
752     //     602..606 'obj2': &dyn Baz<i8, i16>
753     check_infer_with_mismatches(
754         r#"
755         #[lang = "sized"]
756         pub trait Sized {}
757         #[lang = "unsize"]
758         pub trait Unsize<T> {}
759         #[lang = "coerce_unsized"]
760         pub trait CoerceUnsized<T> {}
761
762         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
763
764         trait Foo<T, U> {}
765         trait Bar<U, T, X>: Foo<T, U> {}
766         trait Baz<T, X>: Bar<usize, T, X> {}
767
768         struct S<T, X>;
769         impl<T, X> Foo<T, usize> for S<T, X> {}
770         impl<T, X> Bar<usize, T, X> for S<T, X> {}
771         impl<T, X> Baz<T, X> for S<T, X> {}
772
773         fn test() {
774             let obj: &dyn Baz<i8, i16> = &S;
775             let obj: &dyn Bar<_, _, _> = obj;
776             let obj: &dyn Foo<_, _> = obj;
777             let obj2: &dyn Baz<i8, i16> = &S;
778             let _: &dyn Foo<_, _> = obj2;
779         }
780         "#,
781         expect![[r#"
782             424..609 '{     ...bj2; }': ()
783             434..437 'obj': &dyn Baz<i8, i16>
784             459..461 '&S': &S<i8, i16>
785             460..461 'S': S<i8, i16>
786             471..474 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
787             496..499 'obj': &dyn Baz<i8, i16>
788             509..512 'obj': &dyn Foo<{unknown}, {unknown}>
789             531..534 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
790             544..548 'obj2': &dyn Baz<i8, i16>
791             570..572 '&S': &S<i8, i16>
792             571..572 'S': S<i8, i16>
793             582..583 '_': &dyn Foo<{unknown}, {unknown}>
794             602..606 'obj2': &dyn Baz<i8, i16>
795             496..499: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16>
796             531..534: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}>
797             602..606: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16>
798         "#]],
799     );
800 }
801
802 #[test]
803 fn coerce_unsize_super_trait_cycle() {
804     check_infer_with_mismatches(
805         r#"
806         #[lang = "sized"]
807         pub trait Sized {}
808         #[lang = "unsize"]
809         pub trait Unsize<T> {}
810         #[lang = "coerce_unsized"]
811         pub trait CoerceUnsized<T> {}
812
813         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
814
815         trait A {}
816         trait B: C + A {}
817         trait C: B {}
818         trait D: C
819
820         struct S;
821         impl A for S {}
822         impl B for S {}
823         impl C for S {}
824         impl D for S {}
825
826         fn test() {
827             let obj: &dyn D = &S;
828             let obj: &dyn A = &S;
829         }
830         "#,
831         expect![[r"
832             328..383 '{     ... &S; }': ()
833             338..341 'obj': &dyn D
834             352..354 '&S': &S
835             353..354 'S': S
836             364..367 'obj': &dyn A
837             378..380 '&S': &S
838             379..380 'S': S
839         "]],
840     );
841 }
842
843 #[test]
844 fn coerce_unsize_generic() {
845     // FIXME: fix the type mismatches here
846     check_infer_with_mismatches(
847         r#"
848         #[lang = "unsize"]
849         pub trait Unsize<T> {}
850         #[lang = "coerce_unsized"]
851         pub trait CoerceUnsized<T> {}
852
853         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
854
855         struct Foo<T> { t: T };
856         struct Bar<T>(Foo<T>);
857
858         fn test() {
859             let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
860             let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
861         }
862         "#,
863         expect![[r#"
864             209..317 '{     ... }); }': ()
865             219..220 '_': &Foo<[usize]>
866             238..259 '&Foo {..., 3] }': &Foo<[usize]>
867             239..259 'Foo { ..., 3] }': Foo<[usize]>
868             248..257 '[1, 2, 3]': [usize; 3]
869             249..250 '1': usize
870             252..253 '2': usize
871             255..256 '3': usize
872             269..270 '_': &Bar<[usize]>
873             288..314 '&Bar(F... 3] })': &Bar<[i32; 3]>
874             289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]>
875             289..314 'Bar(Fo... 3] })': Bar<[i32; 3]>
876             293..313 'Foo { ..., 3] }': Foo<[i32; 3]>
877             302..311 '[1, 2, 3]': [i32; 3]
878             303..304 '1': i32
879             306..307 '2': i32
880             309..310 '3': i32
881             248..257: expected [usize], got [usize; 3]
882             288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]>
883         "#]],
884     );
885 }
886
887 #[test]
888 fn coerce_unsize_apit() {
889     // FIXME: #8984
890     check_infer_with_mismatches(
891         r#"
892 #[lang = "sized"]
893 pub trait Sized {}
894 #[lang = "unsize"]
895 pub trait Unsize<T> {}
896 #[lang = "coerce_unsized"]
897 pub trait CoerceUnsized<T> {}
898
899 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
900
901 trait Foo {}
902
903 fn test(f: impl Foo) {
904     let _: &dyn Foo = &f;
905 }
906         "#,
907         expect![[r#"
908             210..211 'f': impl Foo
909             223..252 '{     ... &f; }': ()
910             233..234 '_': &dyn Foo
911             247..249 '&f': &impl Foo
912             248..249 'f': impl Foo
913             247..249: expected &dyn Foo, got &impl Foo
914         "#]],
915     );
916 }
917
918 #[test]
919 fn infer_two_closures_lub() {
920     check_types(
921         r#"
922 fn foo(c: i32) {
923     let add = |a: i32, b: i32| a + b;
924     let sub = |a, b| a - b;
925             //^ |i32, i32| -> i32
926     if c > 42 { add } else { sub };
927   //^ fn(i32, i32) -> i32
928 }
929         "#,
930     )
931 }
932
933 #[test]
934 fn infer_match_diverging_branch_1() {
935     check_types(
936         r#"
937 enum Result<T> { Ok(T), Err }
938 fn parse<T>() -> T { loop {} }
939
940 fn test() -> i32 {
941     let a = match parse() {
942         Ok(val) => val,
943         Err => return 0,
944     };
945     a
946   //^ i32
947 }
948         "#,
949     )
950 }
951
952 #[test]
953 fn infer_match_diverging_branch_2() {
954     // same as 1 except for order of branches
955     check_types(
956         r#"
957 enum Result<T> { Ok(T), Err }
958 fn parse<T>() -> T { loop {} }
959
960 fn test() -> i32 {
961     let a = match parse() {
962         Err => return 0,
963         Ok(val) => val,
964     };
965     a
966   //^ i32
967 }
968         "#,
969     )
970 }
971
972 #[test]
973 fn panic_macro() {
974     check_no_mismatches(
975         r#"
976 mod panic {
977     #[macro_export]
978     pub macro panic_2015 {
979         () => (
980             $crate::panicking::panic()
981         ),
982     }
983 }
984
985 mod panicking {
986     pub fn panic() -> ! { loop {} }
987 }
988
989 #[rustc_builtin_macro = "core_panic"]
990 macro_rules! panic {
991     // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
992     // depending on the edition of the caller.
993     ($($arg:tt)*) => {
994         /* compiler built-in */
995     };
996 }
997
998 fn main() {
999     panic!()
1000 }
1001         "#,
1002     );
1003 }
1004
1005 #[test]
1006 fn coerce_unsize_expected_type() {
1007     check_no_mismatches(
1008         r#"
1009 #[lang = "sized"]
1010 pub trait Sized {}
1011 #[lang = "unsize"]
1012 pub trait Unsize<T> {}
1013 #[lang = "coerce_unsized"]
1014 pub trait CoerceUnsized<T> {}
1015
1016 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
1017
1018 fn main() {
1019     let foo: &[u32] = &[1, 2];
1020     let foo: &[u32] = match true {
1021         true => &[1, 2],
1022         false => &[1, 2, 3],
1023     };
1024     let foo: &[u32] = if true {
1025         &[1, 2]
1026     } else {
1027         &[1, 2, 3]
1028     };
1029 }
1030         "#,
1031     );
1032 }