diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-26 09:19:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-26 09:19:18 +0100 |
commit | 79376abb43e3e1e607b5307e85dd43251ad6c5e3 (patch) | |
tree | 03ab755672e9b973bbcbb9fd86f9d2fdf4f0e1ba /crates/ra_hir/src/ty/tests | |
parent | 6c1878009db50b81fd70b7eb93a76d57a366c7ba (diff) | |
parent | 29e56b8ee480828b81011cfa16c055fa0c9c89fe (diff) |
Merge #1823
1823: Support type coercion r=flodiebold a=uHOOCCOOHu
Co-authored-by: uHOOCCOOHu <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/tests')
-rw-r--r-- | crates/ra_hir/src/ty/tests/coercion.rs | 369 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/never_type.rs | 246 |
2 files changed, 615 insertions, 0 deletions
diff --git a/crates/ra_hir/src/ty/tests/coercion.rs b/crates/ra_hir/src/ty/tests/coercion.rs new file mode 100644 index 000000000..1530fcc63 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/coercion.rs | |||
@@ -0,0 +1,369 @@ | |||
1 | use insta::assert_snapshot; | ||
2 | use test_utils::covers; | ||
3 | |||
4 | // Infer with some common definitions and impls. | ||
5 | fn infer(source: &str) -> String { | ||
6 | let defs = r#" | ||
7 | #[lang = "sized"] | ||
8 | pub trait Sized {} | ||
9 | #[lang = "unsize"] | ||
10 | pub trait Unsize<T: ?Sized> {} | ||
11 | #[lang = "coerce_unsized"] | ||
12 | pub trait CoerceUnsized<T> {} | ||
13 | |||
14 | impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} | ||
15 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} | ||
16 | "#; | ||
17 | |||
18 | // Append to the end to keep positions unchanged. | ||
19 | super::infer(&format!("{}{}", source, defs)) | ||
20 | } | ||
21 | |||
22 | #[test] | ||
23 | fn infer_block_expr_type_mismatch() { | ||
24 | assert_snapshot!( | ||
25 | infer(r#" | ||
26 | fn test() { | ||
27 | let a: i32 = { 1i64 }; | ||
28 | } | ||
29 | "#), | ||
30 | @r###" | ||
31 | [11; 41) '{ ...4 }; }': () | ||
32 | [21; 22) 'a': i32 | ||
33 | [30; 38) '{ 1i64 }': i64 | ||
34 | [32; 36) '1i64': i64 | ||
35 | "###); | ||
36 | } | ||
37 | |||
38 | #[test] | ||
39 | fn coerce_places() { | ||
40 | assert_snapshot!( | ||
41 | infer(r#" | ||
42 | struct S<T> { a: T } | ||
43 | |||
44 | fn f<T>(_: &[T]) -> T { loop {} } | ||
45 | fn g<T>(_: S<&[T]>) -> T { loop {} } | ||
46 | |||
47 | fn gen<T>() -> *mut [T; 2] { loop {} } | ||
48 | fn test1<U>() -> *mut [U] { | ||
49 | gen() | ||
50 | } | ||
51 | |||
52 | fn test2() { | ||
53 | let arr: &[u8; 1] = &[1]; | ||
54 | |||
55 | let a: &[_] = arr; | ||
56 | let b = f(arr); | ||
57 | let c: &[_] = { arr }; | ||
58 | let d = g(S { a: arr }); | ||
59 | let e: [&[_]; 1] = [arr]; | ||
60 | let f: [&[_]; 2] = [arr; 2]; | ||
61 | let g: (&[_], &[_]) = (arr, arr); | ||
62 | } | ||
63 | "#), | ||
64 | @r###" | ||
65 | [31; 32) '_': &[T] | ||
66 | [45; 56) '{ loop {} }': T | ||
67 | [47; 54) 'loop {}': ! | ||
68 | [52; 54) '{}': () | ||
69 | [65; 66) '_': S<&[T]> | ||
70 | [82; 93) '{ loop {} }': T | ||
71 | [84; 91) 'loop {}': ! | ||
72 | [89; 91) '{}': () | ||
73 | [122; 133) '{ loop {} }': *mut [T;_] | ||
74 | [124; 131) 'loop {}': ! | ||
75 | [129; 131) '{}': () | ||
76 | [160; 173) '{ gen() }': *mut [U] | ||
77 | [166; 169) 'gen': fn gen<U>() -> *mut [T;_] | ||
78 | [166; 171) 'gen()': *mut [U;_] | ||
79 | [186; 420) '{ ...rr); }': () | ||
80 | [196; 199) 'arr': &[u8;_] | ||
81 | [212; 216) '&[1]': &[u8;_] | ||
82 | [213; 216) '[1]': [u8;_] | ||
83 | [214; 215) '1': u8 | ||
84 | [227; 228) 'a': &[u8] | ||
85 | [237; 240) 'arr': &[u8;_] | ||
86 | [250; 251) 'b': u8 | ||
87 | [254; 255) 'f': fn f<u8>(&[T]) -> T | ||
88 | [254; 260) 'f(arr)': u8 | ||
89 | [256; 259) 'arr': &[u8;_] | ||
90 | [270; 271) 'c': &[u8] | ||
91 | [280; 287) '{ arr }': &[u8] | ||
92 | [282; 285) 'arr': &[u8;_] | ||
93 | [297; 298) 'd': u8 | ||
94 | [301; 302) 'g': fn g<u8>(S<&[T]>) -> T | ||
95 | [301; 316) 'g(S { a: arr })': u8 | ||
96 | [303; 315) 'S { a: arr }': S<&[u8]> | ||
97 | [310; 313) 'arr': &[u8;_] | ||
98 | [326; 327) 'e': [&[u8];_] | ||
99 | [341; 346) '[arr]': [&[u8];_] | ||
100 | [342; 345) 'arr': &[u8;_] | ||
101 | [356; 357) 'f': [&[u8];_] | ||
102 | [371; 379) '[arr; 2]': [&[u8];_] | ||
103 | [372; 375) 'arr': &[u8;_] | ||
104 | [377; 378) '2': usize | ||
105 | [389; 390) 'g': (&[u8], &[u8]) | ||
106 | [407; 417) '(arr, arr)': (&[u8], &[u8]) | ||
107 | [408; 411) 'arr': &[u8;_] | ||
108 | [413; 416) 'arr': &[u8;_] | ||
109 | "### | ||
110 | ); | ||
111 | } | ||
112 | |||
113 | #[test] | ||
114 | fn infer_let_stmt_coerce() { | ||
115 | assert_snapshot!( | ||
116 | infer(r#" | ||
117 | fn test() { | ||
118 | let x: &[i32] = &[1]; | ||
119 | } | ||
120 | "#), | ||
121 | @r###" | ||
122 | [11; 40) '{ ...[1]; }': () | ||
123 | [21; 22) 'x': &[i32] | ||
124 | [33; 37) '&[1]': &[i32;_] | ||
125 | [34; 37) '[1]': [i32;_] | ||
126 | [35; 36) '1': i32 | ||
127 | "###); | ||
128 | } | ||
129 | |||
130 | #[test] | ||
131 | fn infer_custom_coerce_unsized() { | ||
132 | assert_snapshot!( | ||
133 | infer(r#" | ||
134 | struct A<T: ?Sized>(*const T); | ||
135 | struct B<T: ?Sized>(*const T); | ||
136 | struct C<T: ?Sized> { inner: *const T } | ||
137 | |||
138 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | ||
139 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} | ||
140 | |||
141 | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } | ||
142 | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } | ||
143 | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | ||
144 | |||
145 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | ||
146 | let d = foo1(a); | ||
147 | let e = foo2(b); | ||
148 | let f = foo3(c); | ||
149 | } | ||
150 | "#), | ||
151 | @r###" | ||
152 | [258; 259) 'x': A<[T]> | ||
153 | [279; 284) '{ x }': A<[T]> | ||
154 | [281; 282) 'x': A<[T]> | ||
155 | [296; 297) 'x': B<[T]> | ||
156 | [317; 322) '{ x }': B<[T]> | ||
157 | [319; 320) 'x': B<[T]> | ||
158 | [334; 335) 'x': C<[T]> | ||
159 | [355; 360) '{ x }': C<[T]> | ||
160 | [357; 358) 'x': C<[T]> | ||
161 | [370; 371) 'a': A<[u8;_]> | ||
162 | [385; 386) 'b': B<[u8;_]> | ||
163 | [400; 401) 'c': C<[u8;_]> | ||
164 | [415; 481) '{ ...(c); }': () | ||
165 | [425; 426) 'd': A<[{unknown}]> | ||
166 | [429; 433) 'foo1': fn foo1<{unknown}>(A<[T]>) -> A<[T]> | ||
167 | [429; 436) 'foo1(a)': A<[{unknown}]> | ||
168 | [434; 435) 'a': A<[u8;_]> | ||
169 | [446; 447) 'e': B<[u8]> | ||
170 | [450; 454) 'foo2': fn foo2<u8>(B<[T]>) -> B<[T]> | ||
171 | [450; 457) 'foo2(b)': B<[u8]> | ||
172 | [455; 456) 'b': B<[u8;_]> | ||
173 | [467; 468) 'f': C<[u8]> | ||
174 | [471; 475) 'foo3': fn foo3<u8>(C<[T]>) -> C<[T]> | ||
175 | [471; 478) 'foo3(c)': C<[u8]> | ||
176 | [476; 477) 'c': C<[u8;_]> | ||
177 | "### | ||
178 | ); | ||
179 | } | ||
180 | |||
181 | #[test] | ||
182 | fn infer_if_coerce() { | ||
183 | assert_snapshot!( | ||
184 | infer(r#" | ||
185 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
186 | fn test() { | ||
187 | let x = if true { | ||
188 | foo(&[1]) | ||
189 | } else { | ||
190 | &[1] | ||
191 | }; | ||
192 | } | ||
193 | "#), | ||
194 | @r###" | ||
195 | [11; 12) 'x': &[T] | ||
196 | [28; 39) '{ loop {} }': &[T] | ||
197 | [30; 37) 'loop {}': ! | ||
198 | [35; 37) '{}': () | ||
199 | [50; 126) '{ ... }; }': () | ||
200 | [60; 61) 'x': &[i32] | ||
201 | [64; 123) 'if tru... }': &[i32] | ||
202 | [67; 71) 'true': bool | ||
203 | [72; 97) '{ ... }': &[i32] | ||
204 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
205 | [82; 91) 'foo(&[1])': &[i32] | ||
206 | [86; 90) '&[1]': &[i32;_] | ||
207 | [87; 90) '[1]': [i32;_] | ||
208 | [88; 89) '1': i32 | ||
209 | [103; 123) '{ ... }': &[i32;_] | ||
210 | [113; 117) '&[1]': &[i32;_] | ||
211 | [114; 117) '[1]': [i32;_] | ||
212 | [115; 116) '1': i32 | ||
213 | "### | ||
214 | ); | ||
215 | } | ||
216 | |||
217 | #[test] | ||
218 | fn infer_if_else_coerce() { | ||
219 | assert_snapshot!( | ||
220 | infer(r#" | ||
221 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
222 | fn test() { | ||
223 | let x = if true { | ||
224 | &[1] | ||
225 | } else { | ||
226 | foo(&[1]) | ||
227 | }; | ||
228 | } | ||
229 | "#), | ||
230 | @r###" | ||
231 | [11; 12) 'x': &[T] | ||
232 | [28; 39) '{ loop {} }': &[T] | ||
233 | [30; 37) 'loop {}': ! | ||
234 | [35; 37) '{}': () | ||
235 | [50; 126) '{ ... }; }': () | ||
236 | [60; 61) 'x': &[i32] | ||
237 | [64; 123) 'if tru... }': &[i32] | ||
238 | [67; 71) 'true': bool | ||
239 | [72; 92) '{ ... }': &[i32;_] | ||
240 | [82; 86) '&[1]': &[i32;_] | ||
241 | [83; 86) '[1]': [i32;_] | ||
242 | [84; 85) '1': i32 | ||
243 | [98; 123) '{ ... }': &[i32] | ||
244 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
245 | [108; 117) 'foo(&[1])': &[i32] | ||
246 | [112; 116) '&[1]': &[i32;_] | ||
247 | [113; 116) '[1]': [i32;_] | ||
248 | [114; 115) '1': i32 | ||
249 | "### | ||
250 | ); | ||
251 | } | ||
252 | |||
253 | #[test] | ||
254 | fn infer_match_first_coerce() { | ||
255 | assert_snapshot!( | ||
256 | infer(r#" | ||
257 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
258 | fn test(i: i32) { | ||
259 | let x = match i { | ||
260 | 2 => foo(&[2]), | ||
261 | 1 => &[1], | ||
262 | _ => &[3], | ||
263 | }; | ||
264 | } | ||
265 | "#), | ||
266 | @r###" | ||
267 | [11; 12) 'x': &[T] | ||
268 | [28; 39) '{ loop {} }': &[T] | ||
269 | [30; 37) 'loop {}': ! | ||
270 | [35; 37) '{}': () | ||
271 | [48; 49) 'i': i32 | ||
272 | [56; 150) '{ ... }; }': () | ||
273 | [66; 67) 'x': &[i32] | ||
274 | [70; 147) 'match ... }': &[i32] | ||
275 | [76; 77) 'i': i32 | ||
276 | [88; 89) '2': i32 | ||
277 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
278 | [93; 102) 'foo(&[2])': &[i32] | ||
279 | [97; 101) '&[2]': &[i32;_] | ||
280 | [98; 101) '[2]': [i32;_] | ||
281 | [99; 100) '2': i32 | ||
282 | [112; 113) '1': i32 | ||
283 | [117; 121) '&[1]': &[i32;_] | ||
284 | [118; 121) '[1]': [i32;_] | ||
285 | [119; 120) '1': i32 | ||
286 | [131; 132) '_': i32 | ||
287 | [136; 140) '&[3]': &[i32;_] | ||
288 | [137; 140) '[3]': [i32;_] | ||
289 | [138; 139) '3': i32 | ||
290 | "### | ||
291 | ); | ||
292 | } | ||
293 | |||
294 | #[test] | ||
295 | fn infer_match_second_coerce() { | ||
296 | assert_snapshot!( | ||
297 | infer(r#" | ||
298 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
299 | fn test(i: i32) { | ||
300 | let x = match i { | ||
301 | 1 => &[1], | ||
302 | 2 => foo(&[2]), | ||
303 | _ => &[3], | ||
304 | }; | ||
305 | } | ||
306 | "#), | ||
307 | @r###" | ||
308 | [11; 12) 'x': &[T] | ||
309 | [28; 39) '{ loop {} }': &[T] | ||
310 | [30; 37) 'loop {}': ! | ||
311 | [35; 37) '{}': () | ||
312 | [48; 49) 'i': i32 | ||
313 | [56; 150) '{ ... }; }': () | ||
314 | [66; 67) 'x': &[i32] | ||
315 | [70; 147) 'match ... }': &[i32] | ||
316 | [76; 77) 'i': i32 | ||
317 | [88; 89) '1': i32 | ||
318 | [93; 97) '&[1]': &[i32;_] | ||
319 | [94; 97) '[1]': [i32;_] | ||
320 | [95; 96) '1': i32 | ||
321 | [107; 108) '2': i32 | ||
322 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
323 | [112; 121) 'foo(&[2])': &[i32] | ||
324 | [116; 120) '&[2]': &[i32;_] | ||
325 | [117; 120) '[2]': [i32;_] | ||
326 | [118; 119) '2': i32 | ||
327 | [131; 132) '_': i32 | ||
328 | [136; 140) '&[3]': &[i32;_] | ||
329 | [137; 140) '[3]': [i32;_] | ||
330 | [138; 139) '3': i32 | ||
331 | "### | ||
332 | ); | ||
333 | } | ||
334 | |||
335 | #[test] | ||
336 | fn coerce_merge_one_by_one1() { | ||
337 | covers!(coerce_merge_fail_fallback); | ||
338 | |||
339 | assert_snapshot!( | ||
340 | infer(r#" | ||
341 | fn test() { | ||
342 | let t = &mut 1; | ||
343 | let x = match 1 { | ||
344 | 1 => t as *mut i32, | ||
345 | 2 => t as &i32, | ||
346 | _ => t as *const i32, | ||
347 | }; | ||
348 | } | ||
349 | "#), | ||
350 | @r###" | ||
351 | [11; 145) '{ ... }; }': () | ||
352 | [21; 22) 't': &mut i32 | ||
353 | [25; 31) '&mut 1': &mut i32 | ||
354 | [30; 31) '1': i32 | ||
355 | [41; 42) 'x': *const i32 | ||
356 | [45; 142) 'match ... }': *const i32 | ||
357 | [51; 52) '1': i32 | ||
358 | [63; 64) '1': i32 | ||
359 | [68; 69) 't': &mut i32 | ||
360 | [68; 81) 't as *mut i32': *mut i32 | ||
361 | [91; 92) '2': i32 | ||
362 | [96; 97) 't': &mut i32 | ||
363 | [96; 105) 't as &i32': &i32 | ||
364 | [115; 116) '_': i32 | ||
365 | [120; 121) 't': &mut i32 | ||
366 | [120; 135) 't as *const i32': *const i32 | ||
367 | "### | ||
368 | ); | ||
369 | } | ||
diff --git a/crates/ra_hir/src/ty/tests/never_type.rs b/crates/ra_hir/src/ty/tests/never_type.rs new file mode 100644 index 000000000..c202f545a --- /dev/null +++ b/crates/ra_hir/src/ty/tests/never_type.rs | |||
@@ -0,0 +1,246 @@ | |||
1 | use super::type_at; | ||
2 | |||
3 | #[test] | ||
4 | fn infer_never1() { | ||
5 | let t = type_at( | ||
6 | r#" | ||
7 | //- /main.rs | ||
8 | fn test() { | ||
9 | let t = return; | ||
10 | t<|>; | ||
11 | } | ||
12 | "#, | ||
13 | ); | ||
14 | assert_eq!(t, "!"); | ||
15 | } | ||
16 | |||
17 | #[test] | ||
18 | fn infer_never2() { | ||
19 | let t = type_at( | ||
20 | r#" | ||
21 | //- /main.rs | ||
22 | fn gen<T>() -> T { loop {} } | ||
23 | |||
24 | fn test() { | ||
25 | let a = gen(); | ||
26 | if false { a } else { loop {} }; | ||
27 | a<|>; | ||
28 | } | ||
29 | "#, | ||
30 | ); | ||
31 | assert_eq!(t, "!"); | ||
32 | } | ||
33 | |||
34 | #[test] | ||
35 | fn infer_never3() { | ||
36 | let t = type_at( | ||
37 | r#" | ||
38 | //- /main.rs | ||
39 | fn gen<T>() -> T { loop {} } | ||
40 | |||
41 | fn test() { | ||
42 | let a = gen(); | ||
43 | if false { loop {} } else { a }; | ||
44 | a<|>; | ||
45 | } | ||
46 | "#, | ||
47 | ); | ||
48 | assert_eq!(t, "!"); | ||
49 | } | ||
50 | |||
51 | #[test] | ||
52 | fn never_type_in_generic_args() { | ||
53 | let t = type_at( | ||
54 | r#" | ||
55 | //- /main.rs | ||
56 | enum Option<T> { None, Some(T) } | ||
57 | |||
58 | fn test() { | ||
59 | let a = if true { Option::None } else { Option::Some(return) }; | ||
60 | a<|>; | ||
61 | } | ||
62 | "#, | ||
63 | ); | ||
64 | assert_eq!(t, "Option<!>"); | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn never_type_can_be_reinferred1() { | ||
69 | let t = type_at( | ||
70 | r#" | ||
71 | //- /main.rs | ||
72 | fn gen<T>() -> T { loop {} } | ||
73 | |||
74 | fn test() { | ||
75 | let a = gen(); | ||
76 | if false { loop {} } else { a }; | ||
77 | a<|>; | ||
78 | if false { a }; | ||
79 | } | ||
80 | "#, | ||
81 | ); | ||
82 | assert_eq!(t, "()"); | ||
83 | } | ||
84 | |||
85 | #[test] | ||
86 | fn never_type_can_be_reinferred2() { | ||
87 | let t = type_at( | ||
88 | r#" | ||
89 | //- /main.rs | ||
90 | enum Option<T> { None, Some(T) } | ||
91 | |||
92 | fn test() { | ||
93 | let a = if true { Option::None } else { Option::Some(return) }; | ||
94 | a<|>; | ||
95 | match 42 { | ||
96 | 42 => a, | ||
97 | _ => Option::Some(42), | ||
98 | }; | ||
99 | } | ||
100 | "#, | ||
101 | ); | ||
102 | assert_eq!(t, "Option<i32>"); | ||
103 | } | ||
104 | #[test] | ||
105 | fn never_type_can_be_reinferred3() { | ||
106 | let t = type_at( | ||
107 | r#" | ||
108 | //- /main.rs | ||
109 | enum Option<T> { None, Some(T) } | ||
110 | |||
111 | fn test() { | ||
112 | let a = if true { Option::None } else { Option::Some(return) }; | ||
113 | a<|>; | ||
114 | match 42 { | ||
115 | 42 => a, | ||
116 | _ => Option::Some("str"), | ||
117 | }; | ||
118 | } | ||
119 | "#, | ||
120 | ); | ||
121 | assert_eq!(t, "Option<&str>"); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn match_no_arm() { | ||
126 | let t = type_at( | ||
127 | r#" | ||
128 | //- /main.rs | ||
129 | enum Void {} | ||
130 | |||
131 | fn test(a: Void) { | ||
132 | let t = match a {}; | ||
133 | t<|>; | ||
134 | } | ||
135 | "#, | ||
136 | ); | ||
137 | assert_eq!(t, "!"); | ||
138 | } | ||
139 | |||
140 | #[test] | ||
141 | fn if_never() { | ||
142 | let t = type_at( | ||
143 | r#" | ||
144 | //- /main.rs | ||
145 | fn test() { | ||
146 | let i = if true { | ||
147 | loop {} | ||
148 | } else { | ||
149 | 3.0 | ||
150 | }; | ||
151 | i<|>; | ||
152 | } | ||
153 | "#, | ||
154 | ); | ||
155 | assert_eq!(t, "f64"); | ||
156 | } | ||
157 | |||
158 | #[test] | ||
159 | fn if_else_never() { | ||
160 | let t = type_at( | ||
161 | r#" | ||
162 | //- /main.rs | ||
163 | fn test(input: bool) { | ||
164 | let i = if input { | ||
165 | 2.0 | ||
166 | } else { | ||
167 | return | ||
168 | }; | ||
169 | i<|>; | ||
170 | } | ||
171 | "#, | ||
172 | ); | ||
173 | assert_eq!(t, "f64"); | ||
174 | } | ||
175 | |||
176 | #[test] | ||
177 | fn match_first_arm_never() { | ||
178 | let t = type_at( | ||
179 | r#" | ||
180 | //- /main.rs | ||
181 | fn test(a: i32) { | ||
182 | let i = match a { | ||
183 | 1 => return, | ||
184 | 2 => 2.0, | ||
185 | 3 => loop {}, | ||
186 | _ => 3.0, | ||
187 | }; | ||
188 | i<|>; | ||
189 | } | ||
190 | "#, | ||
191 | ); | ||
192 | assert_eq!(t, "f64"); | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn match_second_arm_never() { | ||
197 | let t = type_at( | ||
198 | r#" | ||
199 | //- /main.rs | ||
200 | fn test(a: i32) { | ||
201 | let i = match a { | ||
202 | 1 => 3.0, | ||
203 | 2 => loop {}, | ||
204 | 3 => 3.0, | ||
205 | _ => return, | ||
206 | }; | ||
207 | i<|>; | ||
208 | } | ||
209 | "#, | ||
210 | ); | ||
211 | assert_eq!(t, "f64"); | ||
212 | } | ||
213 | |||
214 | #[test] | ||
215 | fn match_all_arms_never() { | ||
216 | let t = type_at( | ||
217 | r#" | ||
218 | //- /main.rs | ||
219 | fn test(a: i32) { | ||
220 | let i = match a { | ||
221 | 2 => return, | ||
222 | _ => loop {}, | ||
223 | }; | ||
224 | i<|>; | ||
225 | } | ||
226 | "#, | ||
227 | ); | ||
228 | assert_eq!(t, "!"); | ||
229 | } | ||
230 | |||
231 | #[test] | ||
232 | fn match_no_never_arms() { | ||
233 | let t = type_at( | ||
234 | r#" | ||
235 | //- /main.rs | ||
236 | fn test(a: i32) { | ||
237 | let i = match a { | ||
238 | 2 => 2.0, | ||
239 | _ => 3.0, | ||
240 | }; | ||
241 | i<|>; | ||
242 | } | ||
243 | "#, | ||
244 | ); | ||
245 | assert_eq!(t, "f64"); | ||
246 | } | ||