aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/tests/coercion.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-08-13 15:35:29 +0100
committerAleksey Kladov <[email protected]>2020-08-13 15:35:29 +0100
commit6a77ec7bbe6ddbf663dce9529d11d1bb56c5489a (patch)
treeb6e3d7e0109eb82bca75b5ebc35a7d723542b8dd /crates/hir_ty/src/tests/coercion.rs
parent50f8c1ebf23f634b68529603a917e3feeda457fa (diff)
Rename ra_hir_ty -> hir_ty
Diffstat (limited to 'crates/hir_ty/src/tests/coercion.rs')
-rw-r--r--crates/hir_ty/src/tests/coercion.rs861
1 files changed, 861 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs
new file mode 100644
index 000000000..17efd75cb
--- /dev/null
+++ b/crates/hir_ty/src/tests/coercion.rs
@@ -0,0 +1,861 @@
1use expect::expect;
2use test_utils::mark;
3
4use super::{check_infer, check_infer_with_mismatches};
5
6#[test]
7fn 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]
24fn 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]
109fn 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]
132fn 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]
194fn 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]
236fn 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]
282fn 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]
330fn 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]
383fn 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]
421fn 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]
437fn 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]
472fn 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]
509fn 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]
540fn 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]
571fn 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]
591fn 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]
634fn 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]
653fn 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]
675fn 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]
702fn 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]
748fn 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]
796fn 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]
838fn 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}