rust-analyzer/crates/hir_ty/src/tests/coercion.rs
2020-08-21 13:19:31 +02:00

861 lines
24 KiB
Rust

use expect_test::expect;
use test_utils::mark;
use super::{check_infer, check_infer_with_mismatches};
#[test]
fn infer_block_expr_type_mismatch() {
check_infer(
r"
fn test() {
let a: i32 = { 1i64 };
}
",
expect![[r"
10..40 '{ ...4 }; }': ()
20..21 'a': i32
29..37 '{ 1i64 }': i64
31..35 '1i64': i64
"]],
);
}
#[test]
fn coerce_places() {
check_infer(
r#"
struct S<T> { a: T }
fn f<T>(_: &[T]) -> T { loop {} }
fn g<T>(_: S<&[T]>) -> T { loop {} }
fn gen<T>() -> *mut [T; 2] { loop {} }
fn test1<U>() -> *mut [U] {
gen()
}
fn test2() {
let arr: &[u8; 1] = &[1];
let a: &[_] = arr;
let b = f(arr);
let c: &[_] = { arr };
let d = g(S { a: arr });
let e: [&[_]; 1] = [arr];
let f: [&[_]; 2] = [arr; 2];
let g: (&[_], &[_]) = (arr, arr);
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#,
expect![[r"
30..31 '_': &[T]
44..55 '{ loop {} }': T
46..53 'loop {}': !
51..53 '{}': ()
64..65 '_': S<&[T]>
81..92 '{ loop {} }': T
83..90 'loop {}': !
88..90 '{}': ()
121..132 '{ loop {} }': *mut [T; _]
123..130 'loop {}': !
128..130 '{}': ()
159..172 '{ gen() }': *mut [U]
165..168 'gen': fn gen<U>() -> *mut [U; _]
165..170 'gen()': *mut [U; _]
185..419 '{ ...rr); }': ()
195..198 'arr': &[u8; _]
211..215 '&[1]': &[u8; _]
212..215 '[1]': [u8; _]
213..214 '1': u8
226..227 'a': &[u8]
236..239 'arr': &[u8; _]
249..250 'b': u8
253..254 'f': fn f<u8>(&[u8]) -> u8
253..259 'f(arr)': u8
255..258 'arr': &[u8; _]
269..270 'c': &[u8]
279..286 '{ arr }': &[u8]
281..284 'arr': &[u8; _]
296..297 'd': u8
300..301 'g': fn g<u8>(S<&[u8]>) -> u8
300..315 'g(S { a: arr })': u8
302..314 'S { a: arr }': S<&[u8]>
309..312 'arr': &[u8; _]
325..326 'e': [&[u8]; _]
340..345 '[arr]': [&[u8]; _]
341..344 'arr': &[u8; _]
355..356 'f': [&[u8]; _]
370..378 '[arr; 2]': [&[u8]; _]
371..374 'arr': &[u8; _]
376..377 '2': usize
388..389 'g': (&[u8], &[u8])
406..416 '(arr, arr)': (&[u8], &[u8])
407..410 'arr': &[u8; _]
412..415 'arr': &[u8; _]
"]],
);
}
#[test]
fn infer_let_stmt_coerce() {
check_infer(
r"
fn test() {
let x: &[isize] = &[1];
let x: *const [isize] = &[1];
}
",
expect![[r"
10..75 '{ ...[1]; }': ()
20..21 'x': &[isize]
34..38 '&[1]': &[isize; _]
35..38 '[1]': [isize; _]
36..37 '1': isize
48..49 'x': *const [isize]
68..72 '&[1]': &[isize; _]
69..72 '[1]': [isize; _]
70..71 '1': isize
"]],
);
}
#[test]
fn infer_custom_coerce_unsized() {
check_infer(
r#"
struct A<T: ?Sized>(*const T);
struct B<T: ?Sized>(*const T);
struct C<T: ?Sized> { inner: *const T }
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
let d = foo1(a);
let e = foo2(b);
let f = foo3(c);
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#,
expect![[r"
257..258 'x': A<[T]>
278..283 '{ x }': A<[T]>
280..281 'x': A<[T]>
295..296 'x': B<[T]>
316..321 '{ x }': B<[T]>
318..319 'x': B<[T]>
333..334 'x': C<[T]>
354..359 '{ x }': C<[T]>
356..357 'x': C<[T]>
369..370 'a': A<[u8; _]>
384..385 'b': B<[u8; _]>
399..400 'c': C<[u8; _]>
414..480 '{ ...(c); }': ()
424..425 'd': A<[{unknown}]>
428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
428..435 'foo1(a)': A<[{unknown}]>
433..434 'a': A<[u8; _]>
445..446 'e': B<[u8]>
449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
449..456 'foo2(b)': B<[u8]>
454..455 'b': B<[u8; _]>
466..467 'f': C<[u8]>
470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
470..477 'foo3(c)': C<[u8]>
475..476 'c': C<[u8; _]>
"]],
);
}
#[test]
fn infer_if_coerce() {
check_infer(
r#"
fn foo<T>(x: &[T]) -> &[T] { loop {} }
fn test() {
let x = if true {
foo(&[1])
} else {
&[1]
};
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
"#,
expect![[r"
10..11 'x': &[T]
27..38 '{ loop {} }': &[T]
29..36 'loop {}': !
34..36 '{}': ()
49..125 '{ ... }; }': ()
59..60 'x': &[i32]
63..122 'if tru... }': &[i32]
66..70 'true': bool
71..96 '{ ... }': &[i32]
81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
81..90 'foo(&[1])': &[i32]
85..89 '&[1]': &[i32; _]
86..89 '[1]': [i32; _]
87..88 '1': i32
102..122 '{ ... }': &[i32; _]
112..116 '&[1]': &[i32; _]
113..116 '[1]': [i32; _]
114..115 '1': i32
"]],
);
}
#[test]
fn infer_if_else_coerce() {
check_infer(
r#"
fn foo<T>(x: &[T]) -> &[T] { loop {} }
fn test() {
let x = if true {
&[1]
} else {
foo(&[1])
};
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#,
expect![[r"
10..11 'x': &[T]
27..38 '{ loop {} }': &[T]
29..36 'loop {}': !
34..36 '{}': ()
49..125 '{ ... }; }': ()
59..60 'x': &[i32]
63..122 'if tru... }': &[i32]
66..70 'true': bool
71..91 '{ ... }': &[i32; _]
81..85 '&[1]': &[i32; _]
82..85 '[1]': [i32; _]
83..84 '1': i32
97..122 '{ ... }': &[i32]
107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
107..116 'foo(&[1])': &[i32]
111..115 '&[1]': &[i32; _]
112..115 '[1]': [i32; _]
113..114 '1': i32
"]],
)
}
#[test]
fn infer_match_first_coerce() {
check_infer(
r#"
fn foo<T>(x: &[T]) -> &[T] { loop {} }
fn test(i: i32) {
let x = match i {
2 => foo(&[2]),
1 => &[1],
_ => &[3],
};
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
"#,
expect![[r"
10..11 'x': &[T]
27..38 '{ loop {} }': &[T]
29..36 'loop {}': !
34..36 '{}': ()
47..48 'i': i32
55..149 '{ ... }; }': ()
65..66 'x': &[i32]
69..146 'match ... }': &[i32]
75..76 'i': i32
87..88 '2': i32
87..88 '2': i32
92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
92..101 'foo(&[2])': &[i32]
96..100 '&[2]': &[i32; _]
97..100 '[2]': [i32; _]
98..99 '2': i32
111..112 '1': i32
111..112 '1': i32
116..120 '&[1]': &[i32; _]
117..120 '[1]': [i32; _]
118..119 '1': i32
130..131 '_': i32
135..139 '&[3]': &[i32; _]
136..139 '[3]': [i32; _]
137..138 '3': i32
"]],
);
}
#[test]
fn infer_match_second_coerce() {
check_infer(
r#"
fn foo<T>(x: &[T]) -> &[T] { loop {} }
fn test(i: i32) {
let x = match i {
1 => &[1],
2 => foo(&[2]),
_ => &[3],
};
}
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
"#,
expect![[r"
10..11 'x': &[T]
27..38 '{ loop {} }': &[T]
29..36 'loop {}': !
34..36 '{}': ()
47..48 'i': i32
55..149 '{ ... }; }': ()
65..66 'x': &[i32]
69..146 'match ... }': &[i32]
75..76 'i': i32
87..88 '1': i32
87..88 '1': i32
92..96 '&[1]': &[i32; _]
93..96 '[1]': [i32; _]
94..95 '1': i32
106..107 '2': i32
106..107 '2': i32
111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
111..120 'foo(&[2])': &[i32]
115..119 '&[2]': &[i32; _]
116..119 '[2]': [i32; _]
117..118 '2': i32
130..131 '_': i32
135..139 '&[3]': &[i32; _]
136..139 '[3]': [i32; _]
137..138 '3': i32
"]],
);
}
#[test]
fn coerce_merge_one_by_one1() {
mark::check!(coerce_merge_fail_fallback);
check_infer(
r"
fn test() {
let t = &mut 1;
let x = match 1 {
1 => t as *mut i32,
2 => t as &i32,
_ => t as *const i32,
};
}
",
expect![[r"
10..144 '{ ... }; }': ()
20..21 't': &mut i32
24..30 '&mut 1': &mut i32
29..30 '1': i32
40..41 'x': *const i32
44..141 'match ... }': *const i32
50..51 '1': i32
62..63 '1': i32
62..63 '1': i32
67..68 't': &mut i32
67..80 't as *mut i32': *mut i32
90..91 '2': i32
90..91 '2': i32
95..96 't': &mut i32
95..104 't as &i32': &i32
114..115 '_': i32
119..120 't': &mut i32
119..134 't as *const i32': *const i32
"]],
);
}
#[test]
fn return_coerce_unknown() {
check_infer_with_mismatches(
r"
fn foo() -> u32 {
return unknown;
}
",
expect![[r"
16..39 '{ ...own; }': u32
22..36 'return unknown': !
29..36 'unknown': u32
"]],
);
}
#[test]
fn coerce_autoderef() {
check_infer_with_mismatches(
r"
struct Foo;
fn takes_ref_foo(x: &Foo) {}
fn test() {
takes_ref_foo(&Foo);
takes_ref_foo(&&Foo);
takes_ref_foo(&&&Foo);
}
",
expect![[r"
29..30 'x': &Foo
38..40 '{}': ()
51..132 '{ ...oo); }': ()
57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
57..76 'takes_...(&Foo)': ()
71..75 '&Foo': &Foo
72..75 'Foo': Foo
82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
82..102 'takes_...&&Foo)': ()
96..101 '&&Foo': &&Foo
97..101 '&Foo': &Foo
98..101 'Foo': Foo
108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
108..129 'takes_...&&Foo)': ()
122..128 '&&&Foo': &&&Foo
123..128 '&&Foo': &&Foo
124..128 '&Foo': &Foo
125..128 'Foo': Foo
"]],
);
}
#[test]
fn coerce_autoderef_generic() {
check_infer_with_mismatches(
r"
struct Foo;
fn takes_ref<T>(x: &T) -> T { *x }
fn test() {
takes_ref(&Foo);
takes_ref(&&Foo);
takes_ref(&&&Foo);
}
",
expect![[r"
28..29 'x': &T
40..46 '{ *x }': T
42..44 '*x': T
43..44 'x': &T
57..126 '{ ...oo); }': ()
63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
63..78 'takes_ref(&Foo)': Foo
73..77 '&Foo': &Foo
74..77 'Foo': Foo
84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
84..100 'takes_...&&Foo)': &Foo
94..99 '&&Foo': &&Foo
95..99 '&Foo': &Foo
96..99 'Foo': Foo
106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
106..123 'takes_...&&Foo)': &&Foo
116..122 '&&&Foo': &&&Foo
117..122 '&&Foo': &&Foo
118..122 '&Foo': &Foo
119..122 'Foo': Foo
"]],
);
}
#[test]
fn coerce_autoderef_block() {
check_infer_with_mismatches(
r#"
struct String {}
#[lang = "deref"]
trait Deref { type Target; }
impl Deref for String { type Target = str; }
fn takes_ref_str(x: &str) {}
fn returns_string() -> String { loop {} }
fn test() {
takes_ref_str(&{ returns_string() });
}
"#,
expect![[r"
126..127 'x': &str
135..137 '{}': ()
168..179 '{ loop {} }': String
170..177 'loop {}': !
175..177 '{}': ()
190..235 '{ ... }); }': ()
196..209 'takes_ref_str': fn takes_ref_str(&str)
196..232 'takes_...g() })': ()
210..231 '&{ ret...ng() }': &String
211..231 '{ retu...ng() }': String
213..227 'returns_string': fn returns_string() -> String
213..229 'return...ring()': String
"]],
);
}
#[test]
fn closure_return_coerce() {
check_infer_with_mismatches(
r"
fn foo() {
let x = || {
if true {
return &1u32;
}
&&1u32
};
}
",
expect![[r"
9..105 '{ ... }; }': ()
19..20 'x': || -> &u32
23..102 '|| { ... }': || -> &u32
26..102 '{ ... }': &u32
36..81 'if tru... }': ()
39..43 'true': bool
44..81 '{ ... }': ()
58..70 'return &1u32': !
65..70 '&1u32': &u32
66..70 '1u32': u32
90..96 '&&1u32': &&u32
91..96 '&1u32': &u32
92..96 '1u32': u32
"]],
);
}
#[test]
fn coerce_fn_item_to_fn_ptr() {
check_infer_with_mismatches(
r"
fn foo(x: u32) -> isize { 1 }
fn test() {
let f: fn(u32) -> isize = foo;
}
",
expect![[r"
7..8 'x': u32
24..29 '{ 1 }': isize
26..27 '1': isize
40..78 '{ ...foo; }': ()
50..51 'f': fn(u32) -> isize
72..75 'foo': fn foo(u32) -> isize
"]],
);
}
#[test]
fn coerce_fn_items_in_match_arms() {
mark::check!(coerce_fn_reification);
check_infer_with_mismatches(
r"
fn foo1(x: u32) -> isize { 1 }
fn foo2(x: u32) -> isize { 2 }
fn foo3(x: u32) -> isize { 3 }
fn test() {
let x = match 1 {
1 => foo1,
2 => foo2,
_ => foo3,
};
}
",
expect![[r"
8..9 'x': u32
25..30 '{ 1 }': isize
27..28 '1': isize
39..40 'x': u32
56..61 '{ 2 }': isize
58..59 '2': isize
70..71 'x': u32
87..92 '{ 3 }': isize
89..90 '3': isize
103..192 '{ ... }; }': ()
113..114 'x': fn(u32) -> isize
117..189 'match ... }': fn(u32) -> isize
123..124 '1': i32
135..136 '1': i32
135..136 '1': i32
140..144 'foo1': fn foo1(u32) -> isize
154..155 '2': i32
154..155 '2': i32
159..163 'foo2': fn foo2(u32) -> isize
173..174 '_': i32
178..182 'foo3': fn foo3(u32) -> isize
"]],
);
}
#[test]
fn coerce_closure_to_fn_ptr() {
check_infer_with_mismatches(
r"
fn test() {
let f: fn(u32) -> isize = |x| { 1 };
}
",
expect![[r"
10..54 '{ ...1 }; }': ()
20..21 'f': fn(u32) -> isize
42..51 '|x| { 1 }': |u32| -> isize
43..44 'x': u32
46..51 '{ 1 }': isize
48..49 '1': isize
"]],
);
}
#[test]
fn coerce_placeholder_ref() {
// placeholders should unify, even behind references
check_infer_with_mismatches(
r"
struct S<T> { t: T }
impl<TT> S<TT> {
fn get(&self) -> &TT {
&self.t
}
}
",
expect![[r"
50..54 'self': &S<TT>
63..86 '{ ... }': &TT
73..80 '&self.t': &TT
74..78 'self': &S<TT>
74..80 'self.t': TT
"]],
);
}
#[test]
fn coerce_unsize_array() {
check_infer_with_mismatches(
r#"
#[lang = "unsize"]
pub trait Unsize<T> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
fn test() {
let f: &[usize] = &[1, 2, 3];
}
"#,
expect![[r"
161..198 '{ ... 3]; }': ()
171..172 'f': &[usize]
185..195 '&[1, 2, 3]': &[usize; _]
186..195 '[1, 2, 3]': [usize; _]
187..188 '1': usize
190..191 '2': usize
193..194 '3': usize
"]],
);
}
#[test]
fn coerce_unsize_trait_object_simple() {
check_infer_with_mismatches(
r#"
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
trait Foo<T, U> {}
trait Bar<U, T, X>: Foo<T, U> {}
trait Baz<T, X>: Bar<usize, T, X> {}
struct S<T, X>;
impl<T, X> Foo<T, usize> for S<T, X> {}
impl<T, X> Bar<usize, T, X> for S<T, X> {}
impl<T, X> Baz<T, X> for S<T, X> {}
fn test() {
let obj: &dyn Baz<i8, i16> = &S;
let obj: &dyn Bar<_, i8, i16> = &S;
let obj: &dyn Foo<i8, _> = &S;
}
"#,
expect![[r"
424..539 '{ ... &S; }': ()
434..437 'obj': &dyn Baz<i8, i16>
459..461 '&S': &S<i8, i16>
460..461 'S': S<i8, i16>
471..474 'obj': &dyn Bar<usize, i8, i16>
499..501 '&S': &S<i8, i16>
500..501 'S': S<i8, i16>
511..514 'obj': &dyn Foo<i8, usize>
534..536 '&S': &S<i8, {unknown}>
535..536 'S': S<i8, {unknown}>
"]],
);
}
#[test]
// The rust reference says this should be possible, but rustc doesn't implement
// it. We used to support it, but Chalk doesn't.
#[ignore]
fn coerce_unsize_trait_object_to_trait_object() {
check_infer_with_mismatches(
r#"
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
trait Foo<T, U> {}
trait Bar<U, T, X>: Foo<T, U> {}
trait Baz<T, X>: Bar<usize, T, X> {}
struct S<T, X>;
impl<T, X> Foo<T, usize> for S<T, X> {}
impl<T, X> Bar<usize, T, X> for S<T, X> {}
impl<T, X> Baz<T, X> for S<T, X> {}
fn test() {
let obj: &dyn Baz<i8, i16> = &S;
let obj: &dyn Bar<_, _, _> = obj;
let obj: &dyn Foo<_, _> = obj;
let obj2: &dyn Baz<i8, i16> = &S;
let _: &dyn Foo<_, _> = obj2;
}
"#,
expect![[r"
424..609 '{ ...bj2; }': ()
434..437 'obj': &dyn Baz<i8, i16>
459..461 '&S': &S<i8, i16>
460..461 'S': S<i8, i16>
471..474 'obj': &dyn Bar<usize, i8, i16>
496..499 'obj': &dyn Baz<i8, i16>
509..512 'obj': &dyn Foo<i8, usize>
531..534 'obj': &dyn Bar<usize, i8, i16>
544..548 'obj2': &dyn Baz<i8, i16>
570..572 '&S': &S<i8, i16>
571..572 'S': S<i8, i16>
582..583 '_': &dyn Foo<i8, usize>
602..606 'obj2': &dyn Baz<i8, i16>
"]],
);
}
#[test]
fn coerce_unsize_super_trait_cycle() {
check_infer_with_mismatches(
r#"
#[lang = "sized"]
pub trait Sized {}
#[lang = "unsize"]
pub trait Unsize<T> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
trait A {}
trait B: C + A {}
trait C: B {}
trait D: C
struct S;
impl A for S {}
impl B for S {}
impl C for S {}
impl D for S {}
fn test() {
let obj: &dyn D = &S;
let obj: &dyn A = &S;
}
"#,
expect![[r"
328..383 '{ ... &S; }': ()
338..341 'obj': &dyn D
352..354 '&S': &S
353..354 'S': S
364..367 'obj': &dyn A
378..380 '&S': &S
379..380 'S': S
"]],
);
}
#[ignore]
#[test]
fn coerce_unsize_generic() {
// FIXME: Implement this
// https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions
check_infer_with_mismatches(
r#"
#[lang = "unsize"]
pub trait Unsize<T> {}
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}
impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
struct Foo<T> { t: T };
struct Bar<T>(Foo<T>);
fn test() {
let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
}
"#,
expect![[r"
"]],
);
}