aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/tests/never_type.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/tests/never_type.rs')
-rw-r--r--crates/hir_ty/src/tests/never_type.rs409
1 files changed, 409 insertions, 0 deletions
diff --git a/crates/hir_ty/src/tests/never_type.rs b/crates/hir_ty/src/tests/never_type.rs
new file mode 100644
index 000000000..49538b572
--- /dev/null
+++ b/crates/hir_ty/src/tests/never_type.rs
@@ -0,0 +1,409 @@
1use expect::expect;
2
3use super::{check_infer_with_mismatches, check_types};
4
5#[test]
6fn infer_never1() {
7 check_types(
8 r#"
9fn test() {
10 let t = return;
11 t;
12} //^ !
13"#,
14 );
15}
16
17#[test]
18fn infer_never2() {
19 check_types(
20 r#"
21fn gen<T>() -> T { loop {} }
22
23fn test() {
24 let a = gen();
25 if false { a } else { loop {} };
26 a;
27} //^ !
28"#,
29 );
30}
31
32#[test]
33fn infer_never3() {
34 check_types(
35 r#"
36fn gen<T>() -> T { loop {} }
37
38fn test() {
39 let a = gen();
40 if false { loop {} } else { a };
41 a;
42 //^ !
43}
44"#,
45 );
46}
47
48#[test]
49fn never_type_in_generic_args() {
50 check_types(
51 r#"
52enum Option<T> { None, Some(T) }
53
54fn test() {
55 let a = if true { Option::None } else { Option::Some(return) };
56 a;
57} //^ Option<!>
58"#,
59 );
60}
61
62#[test]
63fn never_type_can_be_reinferred1() {
64 check_types(
65 r#"
66fn gen<T>() -> T { loop {} }
67
68fn test() {
69 let a = gen();
70 if false { loop {} } else { a };
71 a;
72 //^ ()
73 if false { a };
74}
75"#,
76 );
77}
78
79#[test]
80fn never_type_can_be_reinferred2() {
81 check_types(
82 r#"
83enum Option<T> { None, Some(T) }
84
85fn test() {
86 let a = if true { Option::None } else { Option::Some(return) };
87 a;
88 //^ Option<i32>
89 match 42 {
90 42 => a,
91 _ => Option::Some(42),
92 };
93}
94"#,
95 );
96}
97
98#[test]
99fn never_type_can_be_reinferred3() {
100 check_types(
101 r#"
102enum Option<T> { None, Some(T) }
103
104fn test() {
105 let a = if true { Option::None } else { Option::Some(return) };
106 a;
107 //^ Option<&str>
108 match 42 {
109 42 => a,
110 _ => Option::Some("str"),
111 };
112}
113"#,
114 );
115}
116
117#[test]
118fn match_no_arm() {
119 check_types(
120 r#"
121enum Void {}
122
123fn test(a: Void) {
124 let t = match a {};
125 t;
126} //^ !
127"#,
128 );
129}
130
131#[test]
132fn match_unknown_arm() {
133 check_types(
134 r#"
135fn test(a: Option) {
136 let t = match 0 {
137 _ => unknown,
138 };
139 t;
140} //^ {unknown}
141"#,
142 );
143}
144
145#[test]
146fn if_never() {
147 check_types(
148 r#"
149fn test() {
150 let i = if true {
151 loop {}
152 } else {
153 3.0
154 };
155 i;
156} //^ f64
157"#,
158 );
159}
160
161#[test]
162fn if_else_never() {
163 check_types(
164 r#"
165fn test(input: bool) {
166 let i = if input {
167 2.0
168 } else {
169 return
170 };
171 i;
172} //^ f64
173"#,
174 );
175}
176
177#[test]
178fn match_first_arm_never() {
179 check_types(
180 r#"
181fn 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} //^ f64
190"#,
191 );
192}
193
194#[test]
195fn match_second_arm_never() {
196 check_types(
197 r#"
198fn test(a: i32) {
199 let i = match a {
200 1 => 3.0,
201 2 => loop {},
202 3 => 3.0,
203 _ => return,
204 };
205 i;
206} //^ f64
207"#,
208 );
209}
210
211#[test]
212fn match_all_arms_never() {
213 check_types(
214 r#"
215fn test(a: i32) {
216 let i = match a {
217 2 => return,
218 _ => loop {},
219 };
220 i;
221} //^ !
222"#,
223 );
224}
225
226#[test]
227fn match_no_never_arms() {
228 check_types(
229 r#"
230fn test(a: i32) {
231 let i = match a {
232 2 => 2.0,
233 _ => 3.0,
234 };
235 i;
236} //^ f64
237"#,
238 );
239}
240
241#[test]
242fn diverging_expression_1() {
243 check_infer_with_mismatches(
244 r"
245 //- /main.rs
246 fn test1() {
247 let x: u32 = return;
248 }
249 fn test2() {
250 let x: u32 = { return; };
251 }
252 fn test3() {
253 let x: u32 = loop {};
254 }
255 fn test4() {
256 let x: u32 = { loop {} };
257 }
258 fn test5() {
259 let x: u32 = { if true { loop {}; } else { loop {}; } };
260 }
261 fn test6() {
262 let x: u32 = { let y: u32 = { loop {}; }; };
263 }
264 ",
265 expect![[r"
266 11..39 '{ ...urn; }': ()
267 21..22 'x': u32
268 30..36 'return': !
269 51..84 '{ ...; }; }': ()
270 61..62 'x': u32
271 70..81 '{ return; }': u32
272 72..78 'return': !
273 96..125 '{ ... {}; }': ()
274 106..107 'x': u32
275 115..122 'loop {}': !
276 120..122 '{}': ()
277 137..170 '{ ...} }; }': ()
278 147..148 'x': u32
279 156..167 '{ loop {} }': u32
280 158..165 'loop {}': !
281 163..165 '{}': ()
282 182..246 '{ ...} }; }': ()
283 192..193 'x': u32
284 201..243 '{ if t...}; } }': u32
285 203..241 'if tru... {}; }': u32
286 206..210 'true': bool
287 211..223 '{ loop {}; }': u32
288 213..220 'loop {}': !
289 218..220 '{}': ()
290 229..241 '{ loop {}; }': u32
291 231..238 'loop {}': !
292 236..238 '{}': ()
293 258..310 '{ ...; }; }': ()
294 268..269 'x': u32
295 277..307 '{ let ...; }; }': u32
296 283..284 'y': u32
297 292..304 '{ loop {}; }': u32
298 294..301 'loop {}': !
299 299..301 '{}': ()
300 "]],
301 );
302}
303
304#[test]
305fn diverging_expression_2() {
306 check_infer_with_mismatches(
307 r#"
308 //- /main.rs
309 fn test1() {
310 // should give type mismatch
311 let x: u32 = { loop {}; "foo" };
312 }
313 "#,
314 expect![[r#"
315 11..84 '{ ..." }; }': ()
316 54..55 'x': u32
317 63..81 '{ loop...foo" }': &str
318 65..72 'loop {}': !
319 70..72 '{}': ()
320 74..79 '"foo"': &str
321 63..81: expected u32, got &str
322 74..79: expected u32, got &str
323 "#]],
324 );
325}
326
327#[test]
328fn diverging_expression_3_break() {
329 check_infer_with_mismatches(
330 r"
331 //- /main.rs
332 fn test1() {
333 // should give type mismatch
334 let x: u32 = { loop { break; } };
335 }
336 fn test2() {
337 // should give type mismatch
338 let x: u32 = { for a in b { break; }; };
339 // should give type mismatch as well
340 let x: u32 = { for a in b {}; };
341 // should give type mismatch as well
342 let x: u32 = { for a in b { return; }; };
343 }
344 fn test3() {
345 // should give type mismatch
346 let x: u32 = { while true { break; }; };
347 // should give type mismatch as well -- there's an implicit break, even if it's never hit
348 let x: u32 = { while true {}; };
349 // should give type mismatch as well
350 let x: u32 = { while true { return; }; };
351 }
352 ",
353 expect![[r"
354 11..85 '{ ...} }; }': ()
355 54..55 'x': u32
356 63..82 '{ loop...k; } }': ()
357 65..80 'loop { break; }': ()
358 70..80 '{ break; }': ()
359 72..77 'break': !
360 63..82: expected u32, got ()
361 65..80: expected u32, got ()
362 97..343 '{ ...; }; }': ()
363 140..141 'x': u32
364 149..175 '{ for ...; }; }': ()
365 151..172 'for a ...eak; }': ()
366 155..156 'a': {unknown}
367 160..161 'b': {unknown}
368 162..172 '{ break; }': ()
369 164..169 'break': !
370 226..227 'x': u32
371 235..253 '{ for ... {}; }': ()
372 237..250 'for a in b {}': ()
373 241..242 'a': {unknown}
374 246..247 'b': {unknown}
375 248..250 '{}': ()
376 304..305 'x': u32
377 313..340 '{ for ...; }; }': ()
378 315..337 'for a ...urn; }': ()
379 319..320 'a': {unknown}
380 324..325 'b': {unknown}
381 326..337 '{ return; }': ()
382 328..334 'return': !
383 149..175: expected u32, got ()
384 235..253: expected u32, got ()
385 313..340: expected u32, got ()
386 355..654 '{ ...; }; }': ()
387 398..399 'x': u32
388 407..433 '{ whil...; }; }': ()
389 409..430 'while ...eak; }': ()
390 415..419 'true': bool
391 420..430 '{ break; }': ()
392 422..427 'break': !
393 537..538 'x': u32
394 546..564 '{ whil... {}; }': ()
395 548..561 'while true {}': ()
396 554..558 'true': bool
397 559..561 '{}': ()
398 615..616 'x': u32
399 624..651 '{ whil...; }; }': ()
400 626..648 'while ...urn; }': ()
401 632..636 'true': bool
402 637..648 '{ return; }': ()
403 639..645 'return': !
404 407..433: expected u32, got ()
405 546..564: expected u32, got ()
406 624..651: expected u32, got ()
407 "]],
408 );
409}