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