1 use expect_test::expect;
3 use super::{check_infer, check_infer_with_mismatches};
6 fn infer_block_expr_type_mismatch() {
10 let a: i32 = { 1i64 };
14 10..40 '{ ...4 }; }': ()
16 29..37 '{ 1i64 }': i64
28 fn f<T>(_: &[T]) -> T { loop {} }
29 fn g<T>(_: S<&[T]>) -> T { loop {} }
31 fn gen<T>() -> *mut [T; 2] { loop {} }
32 fn test1<U>() -> *mut [U] {
37 let arr: &[u8; 1] = &[1];
41 let c: &[_] = { arr };
42 let d = g(S { a: arr });
43 let e: [&[_]; 1] = [arr];
44 let f: [&[_]; 2] = [arr; 2];
45 let g: (&[_], &[_]) = (arr, arr);
51 pub trait Unsize<T: ?Sized> {}
52 #[lang = "coerce_unsized"]
53 pub trait CoerceUnsized<T> {}
55 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
56 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
60 44..55 '{ loop {} }': T
64 81..92 '{ loop {} }': T
67 121..132 '{ loop {} }': *mut [T; 2]
70 159..172 '{ gen() }': *mut [U]
71 165..168 'gen': fn gen<U>() -> *mut [U; 2]
72 165..170 'gen()': *mut [U; 2]
73 185..419 '{ ...rr); }': ()
74 195..198 'arr': &[u8; 1]
75 211..215 '&[1]': &[u8; 1]
76 212..215 '[1]': [u8; 1]
79 236..239 'arr': &[u8; 1]
81 253..254 'f': fn f<u8>(&[u8]) -> u8
83 255..258 'arr': &[u8; 1]
85 279..286 '{ arr }': &[u8]
86 281..284 'arr': &[u8; 1]
88 300..301 'g': fn g<u8>(S<&[u8]>) -> u8
89 300..315 'g(S { a: arr })': u8
90 302..314 'S { a: arr }': S<&[u8]>
91 309..312 'arr': &[u8; 1]
92 325..326 'e': [&[u8]; 1]
93 340..345 '[arr]': [&[u8]; 1]
94 341..344 'arr': &[u8; 1]
95 355..356 'f': [&[u8]; 2]
96 370..378 '[arr; 2]': [&[u8]; _]
97 371..374 'arr': &[u8; 1]
99 388..389 'g': (&[u8], &[u8])
100 406..416 '(arr, arr)': (&[u8], &[u8])
101 407..410 'arr': &[u8; 1]
102 412..415 'arr': &[u8; 1]
108 fn infer_let_stmt_coerce() {
112 let x: &[isize] = &[1];
113 let x: *const [isize] = &[1];
117 10..75 '{ ...[1]; }': ()
119 34..38 '&[1]': &[isize; 1]
120 35..38 '[1]': [isize; 1]
122 48..49 'x': *const [isize]
123 68..72 '&[1]': &[isize; 1]
124 69..72 '[1]': [isize; 1]
131 fn infer_custom_coerce_unsized() {
134 struct A<T: ?Sized>(*const T);
135 struct B<T: ?Sized>(*const T);
136 struct C<T: ?Sized> { inner: *const T }
138 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
139 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
141 fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
142 fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
143 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
145 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
155 pub trait Unsize<T: ?Sized> {}
156 #[lang = "coerce_unsized"]
157 pub trait CoerceUnsized<T> {}
159 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
160 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
164 278..283 '{ x }': A<[T]>
167 316..321 '{ x }': B<[T]>
170 354..359 '{ x }': C<[T]>
172 369..370 'a': A<[u8; 2]>
173 384..385 'b': B<[u8; 2]>
174 399..400 'c': C<[u8; 2]>
175 414..480 '{ ...(c); }': ()
176 424..425 'd': A<[{unknown}]>
177 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
178 428..435 'foo1(a)': A<[{unknown}]>
179 433..434 'a': A<[u8; 2]>
180 445..446 'e': B<[u8]>
181 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
182 449..456 'foo2(b)': B<[u8]>
183 454..455 'b': B<[u8; 2]>
184 466..467 'f': C<[u8]>
185 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
186 470..477 'foo3(c)': C<[u8]>
187 475..476 'c': C<[u8; 2]>
193 fn infer_if_coerce() {
196 fn foo<T>(x: &[T]) -> &[T] { loop {} }
209 pub trait Unsize<T: ?Sized> {}
213 27..38 '{ loop {} }': &[T]
216 49..125 '{ ... }; }': ()
218 63..122 'if tru... }': &[i32]
220 71..96 '{ ... }': &[i32]
221 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
222 81..90 'foo(&[1])': &[i32]
223 85..89 '&[1]': &[i32; 1]
224 86..89 '[1]': [i32; 1]
226 102..122 '{ ... }': &[i32; 1]
227 112..116 '&[1]': &[i32; 1]
228 113..116 '[1]': [i32; 1]
235 fn infer_if_else_coerce() {
238 fn foo<T>(x: &[T]) -> &[T] { loop {} }
250 pub trait Unsize<T: ?Sized> {}
251 #[lang = "coerce_unsized"]
252 pub trait CoerceUnsized<T> {}
254 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
255 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
259 27..38 '{ loop {} }': &[T]
262 49..125 '{ ... }; }': ()
264 63..122 'if tru... }': &[i32]
266 71..91 '{ ... }': &[i32; 1]
267 81..85 '&[1]': &[i32; 1]
268 82..85 '[1]': [i32; 1]
270 97..122 '{ ... }': &[i32]
271 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
272 107..116 'foo(&[1])': &[i32]
273 111..115 '&[1]': &[i32; 1]
274 112..115 '[1]': [i32; 1]
281 fn infer_match_first_coerce() {
284 fn foo<T>(x: &[T]) -> &[T] { loop {} }
296 pub trait Unsize<T: ?Sized> {}
300 27..38 '{ loop {} }': &[T]
304 55..149 '{ ... }; }': ()
306 69..146 'match ... }': &[i32]
310 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
311 92..101 'foo(&[2])': &[i32]
312 96..100 '&[2]': &[i32; 1]
313 97..100 '[2]': [i32; 1]
317 116..120 '&[1]': &[i32; 1]
318 117..120 '[1]': [i32; 1]
321 135..139 '&[3]': &[i32; 1]
322 136..139 '[3]': [i32; 1]
329 fn infer_match_second_coerce() {
332 fn foo<T>(x: &[T]) -> &[T] { loop {} }
344 pub trait Unsize<T: ?Sized> {}
345 #[lang = "coerce_unsized"]
346 pub trait CoerceUnsized<T> {}
348 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
349 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
353 27..38 '{ loop {} }': &[T]
357 55..149 '{ ... }; }': ()
359 69..146 'match ... }': &[i32]
363 92..96 '&[1]': &[i32; 1]
364 93..96 '[1]': [i32; 1]
368 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
369 111..120 'foo(&[2])': &[i32]
370 115..119 '&[2]': &[i32; 1]
371 116..119 '[2]': [i32; 1]
374 135..139 '&[3]': &[i32; 1]
375 136..139 '[3]': [i32; 1]
382 fn coerce_merge_one_by_one1() {
383 cov_mark::check!(coerce_merge_fail_fallback);
392 _ => t as *const i32,
397 10..144 '{ ... }; }': ()
399 24..30 '&mut 1': &mut i32
401 40..41 'x': *const i32
402 44..141 'match ... }': *const i32
407 67..80 't as *mut i32': *mut i32
411 95..104 't as &i32': &i32
413 119..120 't': &mut i32
414 119..134 't as *const i32': *const i32
420 fn return_coerce_unknown() {
421 check_infer_with_mismatches(
428 16..39 '{ ...own; }': u32
429 22..36 'return unknown': !
430 29..36 'unknown': u32
436 fn coerce_autoderef() {
437 check_infer_with_mismatches(
440 fn takes_ref_foo(x: &Foo) {}
443 takes_ref_foo(&&Foo);
444 takes_ref_foo(&&&Foo);
450 51..132 '{ ...oo); }': ()
451 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
452 57..76 'takes_...(&Foo)': ()
455 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
456 82..102 'takes_...&&Foo)': ()
457 96..101 '&&Foo': &&Foo
460 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
461 108..129 'takes_...&&Foo)': ()
462 122..128 '&&&Foo': &&&Foo
463 123..128 '&&Foo': &&Foo
464 124..128 '&Foo': &Foo
471 fn coerce_autoderef_generic() {
472 check_infer_with_mismatches(
475 fn takes_ref<T>(x: &T) -> T { *x }
487 57..126 '{ ...oo); }': ()
488 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
489 63..78 'takes_ref(&Foo)': Foo
492 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
493 84..100 'takes_...&&Foo)': &Foo
494 94..99 '&&Foo': &&Foo
497 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
498 106..123 'takes_...&&Foo)': &&Foo
499 116..122 '&&&Foo': &&&Foo
500 117..122 '&&Foo': &&Foo
501 118..122 '&Foo': &Foo
508 fn coerce_autoderef_block() {
509 check_infer_with_mismatches(
513 trait Deref { type Target; }
514 impl Deref for String { type Target = str; }
515 fn takes_ref_str(x: &str) {}
516 fn returns_string() -> String { loop {} }
518 takes_ref_str(&{ returns_string() });
524 168..179 '{ loop {} }': String
525 170..177 'loop {}': !
527 190..235 '{ ... }); }': ()
528 196..209 'takes_ref_str': fn takes_ref_str(&str)
529 196..232 'takes_...g() })': ()
530 210..231 '&{ ret...ng() }': &String
531 211..231 '{ retu...ng() }': String
532 213..227 'returns_string': fn returns_string() -> String
533 213..229 'return...ring()': String
539 fn closure_return_coerce() {
540 check_infer_with_mismatches(
552 9..105 '{ ... }; }': ()
553 19..20 'x': || -> &u32
554 23..102 '|| { ... }': || -> &u32
555 26..102 '{ ... }': &u32
556 36..81 'if tru... }': ()
559 58..70 'return &1u32': !
562 90..96 '&&1u32': &&u32
570 fn coerce_fn_item_to_fn_ptr() {
571 check_infer_with_mismatches(
573 fn foo(x: u32) -> isize { 1 }
575 let f: fn(u32) -> isize = foo;
580 24..29 '{ 1 }': isize
582 40..78 '{ ...foo; }': ()
583 50..51 'f': fn(u32) -> isize
584 72..75 'foo': fn foo(u32) -> isize
590 fn coerce_fn_items_in_match_arms() {
591 cov_mark::check!(coerce_fn_reification);
593 check_infer_with_mismatches(
595 fn foo1(x: u32) -> isize { 1 }
596 fn foo2(x: u32) -> isize { 2 }
597 fn foo3(x: u32) -> isize { 3 }
608 25..30 '{ 1 }': isize
611 56..61 '{ 2 }': isize
614 87..92 '{ 3 }': isize
616 103..192 '{ ... }; }': ()
617 113..114 'x': fn(u32) -> isize
618 117..189 'match ... }': fn(u32) -> isize
622 140..144 'foo1': fn foo1(u32) -> isize
625 159..163 'foo2': fn foo2(u32) -> isize
627 178..182 'foo3': fn foo3(u32) -> isize
633 fn coerce_closure_to_fn_ptr() {
634 check_infer_with_mismatches(
637 let f: fn(u32) -> isize = |x| { 1 };
641 10..54 '{ ...1 }; }': ()
642 20..21 'f': fn(u32) -> isize
643 42..51 '|x| { 1 }': |u32| -> isize
645 46..51 '{ 1 }': isize
652 fn coerce_placeholder_ref() {
653 // placeholders should unify, even behind references
654 check_infer_with_mismatches(
658 fn get(&self) -> &TT {
664 50..54 'self': &S<TT>
665 63..86 '{ ... }': &TT
666 73..80 '&self.t': &TT
667 74..78 'self': &S<TT>
674 fn coerce_unsize_array() {
675 check_infer_with_mismatches(
678 pub trait Unsize<T> {}
679 #[lang = "coerce_unsized"]
680 pub trait CoerceUnsized<T> {}
682 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
685 let f: &[usize] = &[1, 2, 3];
689 161..198 '{ ... 3]; }': ()
690 171..172 'f': &[usize]
691 185..195 '&[1, 2, 3]': &[usize; 3]
692 186..195 '[1, 2, 3]': [usize; 3]
701 fn coerce_unsize_trait_object_simple() {
702 check_infer_with_mismatches(
707 pub trait Unsize<T> {}
708 #[lang = "coerce_unsized"]
709 pub trait CoerceUnsized<T> {}
711 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
714 trait Bar<U, T, X>: Foo<T, U> {}
715 trait Baz<T, X>: Bar<usize, T, X> {}
718 impl<T, X> Foo<T, usize> for S<T, X> {}
719 impl<T, X> Bar<usize, T, X> for S<T, X> {}
720 impl<T, X> Baz<T, X> for S<T, X> {}
723 let obj: &dyn Baz<i8, i16> = &S;
724 let obj: &dyn Bar<_, i8, i16> = &S;
725 let obj: &dyn Foo<i8, _> = &S;
729 424..539 '{ ... &S; }': ()
730 434..437 'obj': &dyn Baz<i8, i16>
731 459..461 '&S': &S<i8, i16>
732 460..461 'S': S<i8, i16>
733 471..474 'obj': &dyn Bar<usize, i8, i16>
734 499..501 '&S': &S<i8, i16>
735 500..501 'S': S<i8, i16>
736 511..514 'obj': &dyn Foo<i8, usize>
737 534..536 '&S': &S<i8, {unknown}>
738 535..536 'S': S<i8, {unknown}>
744 // The rust reference says this should be possible, but rustc doesn't implement
745 // it. We used to support it, but Chalk doesn't.
747 fn coerce_unsize_trait_object_to_trait_object() {
748 check_infer_with_mismatches(
753 pub trait Unsize<T> {}
754 #[lang = "coerce_unsized"]
755 pub trait CoerceUnsized<T> {}
757 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
760 trait Bar<U, T, X>: Foo<T, U> {}
761 trait Baz<T, X>: Bar<usize, T, X> {}
764 impl<T, X> Foo<T, usize> for S<T, X> {}
765 impl<T, X> Bar<usize, T, X> for S<T, X> {}
766 impl<T, X> Baz<T, X> for S<T, X> {}
769 let obj: &dyn Baz<i8, i16> = &S;
770 let obj: &dyn Bar<_, _, _> = obj;
771 let obj: &dyn Foo<_, _> = obj;
772 let obj2: &dyn Baz<i8, i16> = &S;
773 let _: &dyn Foo<_, _> = obj2;
777 424..609 '{ ...bj2; }': ()
778 434..437 'obj': &dyn Baz<i8, i16>
779 459..461 '&S': &S<i8, i16>
780 460..461 'S': S<i8, i16>
781 471..474 'obj': &dyn Bar<usize, i8, i16>
782 496..499 'obj': &dyn Baz<i8, i16>
783 509..512 'obj': &dyn Foo<i8, usize>
784 531..534 'obj': &dyn Bar<usize, i8, i16>
785 544..548 'obj2': &dyn Baz<i8, i16>
786 570..572 '&S': &S<i8, i16>
787 571..572 'S': S<i8, i16>
788 582..583 '_': &dyn Foo<i8, usize>
789 602..606 'obj2': &dyn Baz<i8, i16>
795 fn coerce_unsize_super_trait_cycle() {
796 check_infer_with_mismatches(
801 pub trait Unsize<T> {}
802 #[lang = "coerce_unsized"]
803 pub trait CoerceUnsized<T> {}
805 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
819 let obj: &dyn D = &S;
820 let obj: &dyn A = &S;
824 328..383 '{ ... &S; }': ()
825 338..341 'obj': &dyn D
828 364..367 'obj': &dyn A
837 fn coerce_unsize_generic() {
838 // FIXME: Implement this
839 // https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions
840 check_infer_with_mismatches(
843 pub trait Unsize<T> {}
844 #[lang = "coerce_unsized"]
845 pub trait CoerceUnsized<T> {}
847 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
849 struct Foo<T> { t: T };
850 struct Bar<T>(Foo<T>);
853 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
854 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });