]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/coercion.rs
Merge #5748
[rust.git] / crates / hir_ty / src / tests / coercion.rs
1 use expect::expect;
2 use test_utils::mark;
3
4 use super::{check_infer, check_infer_with_mismatches};
5
6 #[test]
7 fn infer_block_expr_type_mismatch() {
8     check_infer(
9         r"
10         fn test() {
11             let a: i32 = { 1i64 };
12         }
13         ",
14         expect![[r"
15             10..40 '{     ...4 }; }': ()
16             20..21 'a': i32
17             29..37 '{ 1i64 }': i64
18             31..35 '1i64': i64
19         "]],
20     );
21 }
22
23 #[test]
24 fn coerce_places() {
25     check_infer(
26         r#"
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         #[lang = "sized"]
50         pub trait Sized {}
51         #[lang = "unsize"]
52         pub trait Unsize<T: ?Sized> {}
53         #[lang = "coerce_unsized"]
54         pub trait CoerceUnsized<T> {}
55
56         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
57         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
58         "#,
59         expect![[r"
60             30..31 '_': &[T]
61             44..55 '{ loop {} }': T
62             46..53 'loop {}': !
63             51..53 '{}': ()
64             64..65 '_': S<&[T]>
65             81..92 '{ loop {} }': T
66             83..90 'loop {}': !
67             88..90 '{}': ()
68             121..132 '{ loop {} }': *mut [T; _]
69             123..130 'loop {}': !
70             128..130 '{}': ()
71             159..172 '{     gen() }': *mut [U]
72             165..168 'gen': fn gen<U>() -> *mut [U; _]
73             165..170 'gen()': *mut [U; _]
74             185..419 '{     ...rr); }': ()
75             195..198 'arr': &[u8; _]
76             211..215 '&[1]': &[u8; _]
77             212..215 '[1]': [u8; _]
78             213..214 '1': u8
79             226..227 'a': &[u8]
80             236..239 'arr': &[u8; _]
81             249..250 'b': u8
82             253..254 'f': fn f<u8>(&[u8]) -> u8
83             253..259 'f(arr)': u8
84             255..258 'arr': &[u8; _]
85             269..270 'c': &[u8]
86             279..286 '{ arr }': &[u8]
87             281..284 'arr': &[u8; _]
88             296..297 'd': u8
89             300..301 'g': fn g<u8>(S<&[u8]>) -> u8
90             300..315 'g(S { a: arr })': u8
91             302..314 'S { a: arr }': S<&[u8]>
92             309..312 'arr': &[u8; _]
93             325..326 'e': [&[u8]; _]
94             340..345 '[arr]': [&[u8]; _]
95             341..344 'arr': &[u8; _]
96             355..356 'f': [&[u8]; _]
97             370..378 '[arr; 2]': [&[u8]; _]
98             371..374 'arr': &[u8; _]
99             376..377 '2': usize
100             388..389 'g': (&[u8], &[u8])
101             406..416 '(arr, arr)': (&[u8], &[u8])
102             407..410 'arr': &[u8; _]
103             412..415 'arr': &[u8; _]
104         "]],
105     );
106 }
107
108 #[test]
109 fn infer_let_stmt_coerce() {
110     check_infer(
111         r"
112         fn test() {
113             let x: &[isize] = &[1];
114             let x: *const [isize] = &[1];
115         }
116         ",
117         expect![[r"
118             10..75 '{     ...[1]; }': ()
119             20..21 'x': &[isize]
120             34..38 '&[1]': &[isize; _]
121             35..38 '[1]': [isize; _]
122             36..37 '1': isize
123             48..49 'x': *const [isize]
124             68..72 '&[1]': &[isize; _]
125             69..72 '[1]': [isize; _]
126             70..71 '1': isize
127         "]],
128     );
129 }
130
131 #[test]
132 fn infer_custom_coerce_unsized() {
133     check_infer(
134         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
153         #[lang = "sized"]
154         pub trait Sized {}
155         #[lang = "unsize"]
156         pub trait Unsize<T: ?Sized> {}
157         #[lang = "coerce_unsized"]
158         pub trait CoerceUnsized<T> {}
159
160         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
161         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
162         "#,
163         expect![[r"
164             257..258 'x': A<[T]>
165             278..283 '{ x }': A<[T]>
166             280..281 'x': A<[T]>
167             295..296 'x': B<[T]>
168             316..321 '{ x }': B<[T]>
169             318..319 'x': B<[T]>
170             333..334 'x': C<[T]>
171             354..359 '{ x }': C<[T]>
172             356..357 'x': C<[T]>
173             369..370 'a': A<[u8; _]>
174             384..385 'b': B<[u8; _]>
175             399..400 'c': C<[u8; _]>
176             414..480 '{     ...(c); }': ()
177             424..425 'd': A<[{unknown}]>
178             428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
179             428..435 'foo1(a)': A<[{unknown}]>
180             433..434 'a': A<[u8; _]>
181             445..446 'e': B<[u8]>
182             449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
183             449..456 'foo2(b)': B<[u8]>
184             454..455 'b': B<[u8; _]>
185             466..467 'f': C<[u8]>
186             470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
187             470..477 'foo3(c)': C<[u8]>
188             475..476 'c': C<[u8; _]>
189         "]],
190     );
191 }
192
193 #[test]
194 fn infer_if_coerce() {
195     check_infer(
196         r#"
197         fn foo<T>(x: &[T]) -> &[T] { loop {} }
198         fn test() {
199             let x = if true {
200                 foo(&[1])
201             } else {
202                 &[1]
203             };
204         }
205
206
207         #[lang = "sized"]
208         pub trait Sized {}
209         #[lang = "unsize"]
210         pub trait Unsize<T: ?Sized> {}
211         "#,
212         expect![[r"
213             10..11 'x': &[T]
214             27..38 '{ loop {} }': &[T]
215             29..36 'loop {}': !
216             34..36 '{}': ()
217             49..125 '{     ...  }; }': ()
218             59..60 'x': &[i32]
219             63..122 'if tru...     }': &[i32]
220             66..70 'true': bool
221             71..96 '{     ...     }': &[i32]
222             81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
223             81..90 'foo(&[1])': &[i32]
224             85..89 '&[1]': &[i32; _]
225             86..89 '[1]': [i32; _]
226             87..88 '1': i32
227             102..122 '{     ...     }': &[i32; _]
228             112..116 '&[1]': &[i32; _]
229             113..116 '[1]': [i32; _]
230             114..115 '1': i32
231         "]],
232     );
233 }
234
235 #[test]
236 fn infer_if_else_coerce() {
237     check_infer(
238         r#"
239         fn foo<T>(x: &[T]) -> &[T] { loop {} }
240         fn test() {
241             let x = if true {
242                 &[1]
243             } else {
244                 foo(&[1])
245             };
246         }
247
248         #[lang = "sized"]
249         pub trait Sized {}
250         #[lang = "unsize"]
251         pub trait Unsize<T: ?Sized> {}
252         #[lang = "coerce_unsized"]
253         pub trait CoerceUnsized<T> {}
254
255         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
256         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
257         "#,
258         expect![[r"
259             10..11 'x': &[T]
260             27..38 '{ loop {} }': &[T]
261             29..36 'loop {}': !
262             34..36 '{}': ()
263             49..125 '{     ...  }; }': ()
264             59..60 'x': &[i32]
265             63..122 'if tru...     }': &[i32]
266             66..70 'true': bool
267             71..91 '{     ...     }': &[i32; _]
268             81..85 '&[1]': &[i32; _]
269             82..85 '[1]': [i32; _]
270             83..84 '1': i32
271             97..122 '{     ...     }': &[i32]
272             107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
273             107..116 'foo(&[1])': &[i32]
274             111..115 '&[1]': &[i32; _]
275             112..115 '[1]': [i32; _]
276             113..114 '1': i32
277         "]],
278     )
279 }
280
281 #[test]
282 fn infer_match_first_coerce() {
283     check_infer(
284         r#"
285         fn foo<T>(x: &[T]) -> &[T] { loop {} }
286         fn test(i: i32) {
287             let x = match i {
288                 2 => foo(&[2]),
289                 1 => &[1],
290                 _ => &[3],
291             };
292         }
293
294         #[lang = "sized"]
295         pub trait Sized {}
296         #[lang = "unsize"]
297         pub trait Unsize<T: ?Sized> {}
298         "#,
299         expect![[r"
300             10..11 'x': &[T]
301             27..38 '{ loop {} }': &[T]
302             29..36 'loop {}': !
303             34..36 '{}': ()
304             47..48 'i': i32
305             55..149 '{     ...  }; }': ()
306             65..66 'x': &[i32]
307             69..146 'match ...     }': &[i32]
308             75..76 'i': i32
309             87..88 '2': i32
310             87..88 '2': i32
311             92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
312             92..101 'foo(&[2])': &[i32]
313             96..100 '&[2]': &[i32; _]
314             97..100 '[2]': [i32; _]
315             98..99 '2': i32
316             111..112 '1': i32
317             111..112 '1': i32
318             116..120 '&[1]': &[i32; _]
319             117..120 '[1]': [i32; _]
320             118..119 '1': i32
321             130..131 '_': i32
322             135..139 '&[3]': &[i32; _]
323             136..139 '[3]': [i32; _]
324             137..138 '3': i32
325     "]],
326     );
327 }
328
329 #[test]
330 fn infer_match_second_coerce() {
331     check_infer(
332         r#"
333         fn foo<T>(x: &[T]) -> &[T] { loop {} }
334         fn test(i: i32) {
335             let x = match i {
336                 1 => &[1],
337                 2 => foo(&[2]),
338                 _ => &[3],
339             };
340         }
341
342         #[lang = "sized"]
343         pub trait Sized {}
344         #[lang = "unsize"]
345         pub trait Unsize<T: ?Sized> {}
346         #[lang = "coerce_unsized"]
347         pub trait CoerceUnsized<T> {}
348
349         impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
350         impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
351         "#,
352         expect![[r"
353             10..11 'x': &[T]
354             27..38 '{ loop {} }': &[T]
355             29..36 'loop {}': !
356             34..36 '{}': ()
357             47..48 'i': i32
358             55..149 '{     ...  }; }': ()
359             65..66 'x': &[i32]
360             69..146 'match ...     }': &[i32]
361             75..76 'i': i32
362             87..88 '1': i32
363             87..88 '1': i32
364             92..96 '&[1]': &[i32; _]
365             93..96 '[1]': [i32; _]
366             94..95 '1': i32
367             106..107 '2': i32
368             106..107 '2': i32
369             111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
370             111..120 'foo(&[2])': &[i32]
371             115..119 '&[2]': &[i32; _]
372             116..119 '[2]': [i32; _]
373             117..118 '2': i32
374             130..131 '_': i32
375             135..139 '&[3]': &[i32; _]
376             136..139 '[3]': [i32; _]
377             137..138 '3': i32
378     "]],
379     );
380 }
381
382 #[test]
383 fn coerce_merge_one_by_one1() {
384     mark::check!(coerce_merge_fail_fallback);
385
386     check_infer(
387         r"
388         fn test() {
389             let t = &mut 1;
390             let x = match 1 {
391                 1 => t as *mut i32,
392                 2 => t as &i32,
393                 _ => t as *const i32,
394             };
395         }
396         ",
397         expect![[r"
398             10..144 '{     ...  }; }': ()
399             20..21 't': &mut i32
400             24..30 '&mut 1': &mut i32
401             29..30 '1': i32
402             40..41 'x': *const i32
403             44..141 'match ...     }': *const i32
404             50..51 '1': i32
405             62..63 '1': i32
406             62..63 '1': i32
407             67..68 't': &mut i32
408             67..80 't as *mut i32': *mut i32
409             90..91 '2': i32
410             90..91 '2': i32
411             95..96 't': &mut i32
412             95..104 't as &i32': &i32
413             114..115 '_': i32
414             119..120 't': &mut i32
415             119..134 't as *const i32': *const i32
416     "]],
417     );
418 }
419
420 #[test]
421 fn return_coerce_unknown() {
422     check_infer_with_mismatches(
423         r"
424         fn foo() -> u32 {
425             return unknown;
426         }
427         ",
428         expect![[r"
429             16..39 '{     ...own; }': u32
430             22..36 'return unknown': !
431             29..36 'unknown': u32
432         "]],
433     );
434 }
435
436 #[test]
437 fn coerce_autoderef() {
438     check_infer_with_mismatches(
439         r"
440         struct Foo;
441         fn takes_ref_foo(x: &Foo) {}
442         fn test() {
443             takes_ref_foo(&Foo);
444             takes_ref_foo(&&Foo);
445             takes_ref_foo(&&&Foo);
446         }
447         ",
448         expect![[r"
449             29..30 'x': &Foo
450             38..40 '{}': ()
451             51..132 '{     ...oo); }': ()
452             57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
453             57..76 'takes_...(&Foo)': ()
454             71..75 '&Foo': &Foo
455             72..75 'Foo': Foo
456             82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
457             82..102 'takes_...&&Foo)': ()
458             96..101 '&&Foo': &&Foo
459             97..101 '&Foo': &Foo
460             98..101 'Foo': Foo
461             108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
462             108..129 'takes_...&&Foo)': ()
463             122..128 '&&&Foo': &&&Foo
464             123..128 '&&Foo': &&Foo
465             124..128 '&Foo': &Foo
466             125..128 'Foo': Foo
467         "]],
468     );
469 }
470
471 #[test]
472 fn coerce_autoderef_generic() {
473     check_infer_with_mismatches(
474         r"
475         struct Foo;
476         fn takes_ref<T>(x: &T) -> T { *x }
477         fn test() {
478             takes_ref(&Foo);
479             takes_ref(&&Foo);
480             takes_ref(&&&Foo);
481         }
482         ",
483         expect![[r"
484             28..29 'x': &T
485             40..46 '{ *x }': T
486             42..44 '*x': T
487             43..44 'x': &T
488             57..126 '{     ...oo); }': ()
489             63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
490             63..78 'takes_ref(&Foo)': Foo
491             73..77 '&Foo': &Foo
492             74..77 'Foo': Foo
493             84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
494             84..100 'takes_...&&Foo)': &Foo
495             94..99 '&&Foo': &&Foo
496             95..99 '&Foo': &Foo
497             96..99 'Foo': Foo
498             106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
499             106..123 'takes_...&&Foo)': &&Foo
500             116..122 '&&&Foo': &&&Foo
501             117..122 '&&Foo': &&Foo
502             118..122 '&Foo': &Foo
503             119..122 'Foo': Foo
504         "]],
505     );
506 }
507
508 #[test]
509 fn coerce_autoderef_block() {
510     check_infer_with_mismatches(
511         r#"
512         struct String {}
513         #[lang = "deref"]
514         trait Deref { type Target; }
515         impl Deref for String { type Target = str; }
516         fn takes_ref_str(x: &str) {}
517         fn returns_string() -> String { loop {} }
518         fn test() {
519             takes_ref_str(&{ returns_string() });
520         }
521         "#,
522         expect![[r"
523             126..127 'x': &str
524             135..137 '{}': ()
525             168..179 '{ loop {} }': String
526             170..177 'loop {}': !
527             175..177 '{}': ()
528             190..235 '{     ... }); }': ()
529             196..209 'takes_ref_str': fn takes_ref_str(&str)
530             196..232 'takes_...g() })': ()
531             210..231 '&{ ret...ng() }': &String
532             211..231 '{ retu...ng() }': String
533             213..227 'returns_string': fn returns_string() -> String
534             213..229 'return...ring()': String
535         "]],
536     );
537 }
538
539 #[test]
540 fn closure_return_coerce() {
541     check_infer_with_mismatches(
542         r"
543         fn foo() {
544             let x = || {
545                 if true {
546                     return &1u32;
547                 }
548                 &&1u32
549             };
550         }
551         ",
552         expect![[r"
553             9..105 '{     ...  }; }': ()
554             19..20 'x': || -> &u32
555             23..102 '|| {  ...     }': || -> &u32
556             26..102 '{     ...     }': &u32
557             36..81 'if tru...     }': ()
558             39..43 'true': bool
559             44..81 '{     ...     }': ()
560             58..70 'return &1u32': !
561             65..70 '&1u32': &u32
562             66..70 '1u32': u32
563             90..96 '&&1u32': &&u32
564             91..96 '&1u32': &u32
565             92..96 '1u32': u32
566         "]],
567     );
568 }
569
570 #[test]
571 fn coerce_fn_item_to_fn_ptr() {
572     check_infer_with_mismatches(
573         r"
574         fn foo(x: u32) -> isize { 1 }
575         fn test() {
576             let f: fn(u32) -> isize = foo;
577         }
578         ",
579         expect![[r"
580             7..8 'x': u32
581             24..29 '{ 1 }': isize
582             26..27 '1': isize
583             40..78 '{     ...foo; }': ()
584             50..51 'f': fn(u32) -> isize
585             72..75 'foo': fn foo(u32) -> isize
586         "]],
587     );
588 }
589
590 #[test]
591 fn coerce_fn_items_in_match_arms() {
592     mark::check!(coerce_fn_reification);
593
594     check_infer_with_mismatches(
595         r"
596         fn foo1(x: u32) -> isize { 1 }
597         fn foo2(x: u32) -> isize { 2 }
598         fn foo3(x: u32) -> isize { 3 }
599         fn test() {
600             let x = match 1 {
601                 1 => foo1,
602                 2 => foo2,
603                 _ => foo3,
604             };
605         }
606         ",
607         expect![[r"
608             8..9 'x': u32
609             25..30 '{ 1 }': isize
610             27..28 '1': isize
611             39..40 'x': u32
612             56..61 '{ 2 }': isize
613             58..59 '2': isize
614             70..71 'x': u32
615             87..92 '{ 3 }': isize
616             89..90 '3': isize
617             103..192 '{     ...  }; }': ()
618             113..114 'x': fn(u32) -> isize
619             117..189 'match ...     }': fn(u32) -> isize
620             123..124 '1': i32
621             135..136 '1': i32
622             135..136 '1': i32
623             140..144 'foo1': fn foo1(u32) -> isize
624             154..155 '2': i32
625             154..155 '2': i32
626             159..163 'foo2': fn foo2(u32) -> isize
627             173..174 '_': i32
628             178..182 'foo3': fn foo3(u32) -> isize
629         "]],
630     );
631 }
632
633 #[test]
634 fn coerce_closure_to_fn_ptr() {
635     check_infer_with_mismatches(
636         r"
637         fn test() {
638             let f: fn(u32) -> isize = |x| { 1 };
639         }
640         ",
641         expect![[r"
642             10..54 '{     ...1 }; }': ()
643             20..21 'f': fn(u32) -> isize
644             42..51 '|x| { 1 }': |u32| -> isize
645             43..44 'x': u32
646             46..51 '{ 1 }': isize
647             48..49 '1': isize
648         "]],
649     );
650 }
651
652 #[test]
653 fn coerce_placeholder_ref() {
654     // placeholders should unify, even behind references
655     check_infer_with_mismatches(
656         r"
657         struct S<T> { t: T }
658         impl<TT> S<TT> {
659             fn get(&self) -> &TT {
660                 &self.t
661             }
662         }
663         ",
664         expect![[r"
665             50..54 'self': &S<TT>
666             63..86 '{     ...     }': &TT
667             73..80 '&self.t': &TT
668             74..78 'self': &S<TT>
669             74..80 'self.t': TT
670         "]],
671     );
672 }
673
674 #[test]
675 fn coerce_unsize_array() {
676     check_infer_with_mismatches(
677         r#"
678         #[lang = "unsize"]
679         pub trait Unsize<T> {}
680         #[lang = "coerce_unsized"]
681         pub trait CoerceUnsized<T> {}
682
683         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
684
685         fn test() {
686             let f: &[usize] = &[1, 2, 3];
687         }
688         "#,
689         expect![[r"
690             161..198 '{     ... 3]; }': ()
691             171..172 'f': &[usize]
692             185..195 '&[1, 2, 3]': &[usize; _]
693             186..195 '[1, 2, 3]': [usize; _]
694             187..188 '1': usize
695             190..191 '2': usize
696             193..194 '3': usize
697         "]],
698     );
699 }
700
701 #[test]
702 fn coerce_unsize_trait_object_simple() {
703     check_infer_with_mismatches(
704         r#"
705         #[lang = "sized"]
706         pub trait Sized {}
707         #[lang = "unsize"]
708         pub trait Unsize<T> {}
709         #[lang = "coerce_unsized"]
710         pub trait CoerceUnsized<T> {}
711
712         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
713
714         trait Foo<T, U> {}
715         trait Bar<U, T, X>: Foo<T, U> {}
716         trait Baz<T, X>: Bar<usize, T, X> {}
717
718         struct S<T, X>;
719         impl<T, X> Foo<T, usize> for S<T, X> {}
720         impl<T, X> Bar<usize, T, X> for S<T, X> {}
721         impl<T, X> Baz<T, X> for S<T, X> {}
722
723         fn test() {
724             let obj: &dyn Baz<i8, i16> = &S;
725             let obj: &dyn Bar<_, i8, i16> = &S;
726             let obj: &dyn Foo<i8, _> = &S;
727         }
728         "#,
729         expect![[r"
730             424..539 '{     ... &S; }': ()
731             434..437 'obj': &dyn Baz<i8, i16>
732             459..461 '&S': &S<i8, i16>
733             460..461 'S': S<i8, i16>
734             471..474 'obj': &dyn Bar<usize, i8, i16>
735             499..501 '&S': &S<i8, i16>
736             500..501 'S': S<i8, i16>
737             511..514 'obj': &dyn Foo<i8, usize>
738             534..536 '&S': &S<i8, {unknown}>
739             535..536 'S': S<i8, {unknown}>
740         "]],
741     );
742 }
743
744 #[test]
745 // The rust reference says this should be possible, but rustc doesn't implement
746 // it. We used to support it, but Chalk doesn't.
747 #[ignore]
748 fn coerce_unsize_trait_object_to_trait_object() {
749     check_infer_with_mismatches(
750         r#"
751         #[lang = "sized"]
752         pub trait Sized {}
753         #[lang = "unsize"]
754         pub trait Unsize<T> {}
755         #[lang = "coerce_unsized"]
756         pub trait CoerceUnsized<T> {}
757
758         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
759
760         trait Foo<T, U> {}
761         trait Bar<U, T, X>: Foo<T, U> {}
762         trait Baz<T, X>: Bar<usize, T, X> {}
763
764         struct S<T, X>;
765         impl<T, X> Foo<T, usize> for S<T, X> {}
766         impl<T, X> Bar<usize, T, X> for S<T, X> {}
767         impl<T, X> Baz<T, X> for S<T, X> {}
768
769         fn test() {
770             let obj: &dyn Baz<i8, i16> = &S;
771             let obj: &dyn Bar<_, _, _> = obj;
772             let obj: &dyn Foo<_, _> = obj;
773             let obj2: &dyn Baz<i8, i16> = &S;
774             let _: &dyn Foo<_, _> = obj2;
775         }
776         "#,
777         expect![[r"
778             424..609 '{     ...bj2; }': ()
779             434..437 'obj': &dyn Baz<i8, i16>
780             459..461 '&S': &S<i8, i16>
781             460..461 'S': S<i8, i16>
782             471..474 'obj': &dyn Bar<usize, i8, i16>
783             496..499 'obj': &dyn Baz<i8, i16>
784             509..512 'obj': &dyn Foo<i8, usize>
785             531..534 'obj': &dyn Bar<usize, i8, i16>
786             544..548 'obj2': &dyn Baz<i8, i16>
787             570..572 '&S': &S<i8, i16>
788             571..572 'S': S<i8, i16>
789             582..583 '_': &dyn Foo<i8, usize>
790             602..606 'obj2': &dyn Baz<i8, i16>
791         "]],
792     );
793 }
794
795 #[test]
796 fn coerce_unsize_super_trait_cycle() {
797     check_infer_with_mismatches(
798         r#"
799         #[lang = "sized"]
800         pub trait Sized {}
801         #[lang = "unsize"]
802         pub trait Unsize<T> {}
803         #[lang = "coerce_unsized"]
804         pub trait CoerceUnsized<T> {}
805
806         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
807
808         trait A {}
809         trait B: C + A {}
810         trait C: B {}
811         trait D: C
812
813         struct S;
814         impl A for S {}
815         impl B for S {}
816         impl C for S {}
817         impl D for S {}
818
819         fn test() {
820             let obj: &dyn D = &S;
821             let obj: &dyn A = &S;
822         }
823         "#,
824         expect![[r"
825             328..383 '{     ... &S; }': ()
826             338..341 'obj': &dyn D
827             352..354 '&S': &S
828             353..354 'S': S
829             364..367 'obj': &dyn A
830             378..380 '&S': &S
831             379..380 'S': S
832         "]],
833     );
834 }
835
836 #[ignore]
837 #[test]
838 fn coerce_unsize_generic() {
839     // FIXME: Implement this
840     // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions
841     check_infer_with_mismatches(
842         r#"
843         #[lang = "unsize"]
844         pub trait Unsize<T> {}
845         #[lang = "coerce_unsized"]
846         pub trait CoerceUnsized<T> {}
847
848         impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
849
850         struct Foo<T> { t: T };
851         struct Bar<T>(Foo<T>);
852
853         fn test() {
854             let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
855             let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
856         }
857         "#,
858         expect![[r"
859         "]],
860     );
861 }