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