diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-05-08 19:09:25 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-05-08 19:09:25 +0100 |
commit | f9ec7cebef732fbc9d4849d87d325efef5faadea (patch) | |
tree | 4a40dbed04c432dee54f8a8d016c89c7411b1e6d /crates/ra_hir_ty/src/tests | |
parent | f1fa9aa4c4d4fcfe7d6e90ba9cefca90bc7c4998 (diff) | |
parent | d0129c4ddba3b72e7b26e94e9c25546d37dbf166 (diff) |
Merge #4377
4377: Implement better handling of divergence r=matklad a=flodiebold
Divergence here means that for some reason, the end of a block will not be reached. We tried to model this just using the never type, but that doesn't work fully (e.g. in `let x = { loop {}; "foo" };` x should still have type `&str`); so this introduces a `diverges` flag that the type checker keeps track of, like rustc does. We also add some checking for `break`, but no support for break-with-value or labeled breaks yet.
Co-authored-by: Florian Diebold <[email protected]>
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir_ty/src/tests')
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/never_type.rs | 177 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 10 |
4 files changed, 184 insertions, 9 deletions
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index e6fb3e123..0c3a833bd 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -384,7 +384,7 @@ fn foo() -> u32 { | |||
384 | } | 384 | } |
385 | "#, true), | 385 | "#, true), |
386 | @r###" | 386 | @r###" |
387 | 17..40 '{ ...own; }': ! | 387 | 17..40 '{ ...own; }': u32 |
388 | 23..37 'return unknown': ! | 388 | 23..37 'return unknown': ! |
389 | 30..37 'unknown': u32 | 389 | 30..37 'unknown': u32 |
390 | "### | 390 | "### |
@@ -514,7 +514,7 @@ fn foo() { | |||
514 | 27..103 '{ ... }': &u32 | 514 | 27..103 '{ ... }': &u32 |
515 | 37..82 'if tru... }': () | 515 | 37..82 'if tru... }': () |
516 | 40..44 'true': bool | 516 | 40..44 'true': bool |
517 | 45..82 '{ ... }': ! | 517 | 45..82 '{ ... }': () |
518 | 59..71 'return &1u32': ! | 518 | 59..71 'return &1u32': ! |
519 | 66..71 '&1u32': &u32 | 519 | 66..71 '&1u32': &u32 |
520 | 67..71 '1u32': u32 | 520 | 67..71 '1u32': u32 |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 07398ddcc..4c6099aa2 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -197,7 +197,7 @@ fn spam() { | |||
197 | !0..6 '1isize': isize | 197 | !0..6 '1isize': isize |
198 | !0..6 '1isize': isize | 198 | !0..6 '1isize': isize |
199 | !0..6 '1isize': isize | 199 | !0..6 '1isize': isize |
200 | 54..457 '{ ...!(); }': ! | 200 | 54..457 '{ ...!(); }': () |
201 | 88..109 'spam!(...am!())': {unknown} | 201 | 88..109 'spam!(...am!())': {unknown} |
202 | 115..134 'for _ ...!() {}': () | 202 | 115..134 'for _ ...!() {}': () |
203 | 119..120 '_': {unknown} | 203 | 119..120 '_': {unknown} |
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs index a77209480..082c47208 100644 --- a/crates/ra_hir_ty/src/tests/never_type.rs +++ b/crates/ra_hir_ty/src/tests/never_type.rs | |||
@@ -1,4 +1,6 @@ | |||
1 | use super::type_at; | 1 | use insta::assert_snapshot; |
2 | |||
3 | use super::{infer_with_mismatches, type_at}; | ||
2 | 4 | ||
3 | #[test] | 5 | #[test] |
4 | fn infer_never1() { | 6 | fn infer_never1() { |
@@ -261,3 +263,176 @@ fn test(a: i32) { | |||
261 | ); | 263 | ); |
262 | assert_eq!(t, "f64"); | 264 | assert_eq!(t, "f64"); |
263 | } | 265 | } |
266 | |||
267 | #[test] | ||
268 | fn diverging_expression_1() { | ||
269 | let t = infer_with_mismatches( | ||
270 | r#" | ||
271 | //- /main.rs | ||
272 | fn test1() { | ||
273 | let x: u32 = return; | ||
274 | } | ||
275 | fn test2() { | ||
276 | let x: u32 = { return; }; | ||
277 | } | ||
278 | fn test3() { | ||
279 | let x: u32 = loop {}; | ||
280 | } | ||
281 | fn test4() { | ||
282 | let x: u32 = { loop {} }; | ||
283 | } | ||
284 | fn test5() { | ||
285 | let x: u32 = { if true { loop {}; } else { loop {}; } }; | ||
286 | } | ||
287 | fn test6() { | ||
288 | let x: u32 = { let y: u32 = { loop {}; }; }; | ||
289 | } | ||
290 | "#, | ||
291 | true, | ||
292 | ); | ||
293 | assert_snapshot!(t, @r###" | ||
294 | 25..53 '{ ...urn; }': () | ||
295 | 35..36 'x': u32 | ||
296 | 44..50 'return': ! | ||
297 | 65..98 '{ ...; }; }': () | ||
298 | 75..76 'x': u32 | ||
299 | 84..95 '{ return; }': u32 | ||
300 | 86..92 'return': ! | ||
301 | 110..139 '{ ... {}; }': () | ||
302 | 120..121 'x': u32 | ||
303 | 129..136 'loop {}': ! | ||
304 | 134..136 '{}': () | ||
305 | 151..184 '{ ...} }; }': () | ||
306 | 161..162 'x': u32 | ||
307 | 170..181 '{ loop {} }': u32 | ||
308 | 172..179 'loop {}': ! | ||
309 | 177..179 '{}': () | ||
310 | 196..260 '{ ...} }; }': () | ||
311 | 206..207 'x': u32 | ||
312 | 215..257 '{ if t...}; } }': u32 | ||
313 | 217..255 'if tru... {}; }': u32 | ||
314 | 220..224 'true': bool | ||
315 | 225..237 '{ loop {}; }': u32 | ||
316 | 227..234 'loop {}': ! | ||
317 | 232..234 '{}': () | ||
318 | 243..255 '{ loop {}; }': u32 | ||
319 | 245..252 'loop {}': ! | ||
320 | 250..252 '{}': () | ||
321 | 272..324 '{ ...; }; }': () | ||
322 | 282..283 'x': u32 | ||
323 | 291..321 '{ let ...; }; }': u32 | ||
324 | 297..298 'y': u32 | ||
325 | 306..318 '{ loop {}; }': u32 | ||
326 | 308..315 'loop {}': ! | ||
327 | 313..315 '{}': () | ||
328 | "###); | ||
329 | } | ||
330 | |||
331 | #[test] | ||
332 | fn diverging_expression_2() { | ||
333 | let t = infer_with_mismatches( | ||
334 | r#" | ||
335 | //- /main.rs | ||
336 | fn test1() { | ||
337 | // should give type mismatch | ||
338 | let x: u32 = { loop {}; "foo" }; | ||
339 | } | ||
340 | "#, | ||
341 | true, | ||
342 | ); | ||
343 | assert_snapshot!(t, @r###" | ||
344 | 25..98 '{ ..." }; }': () | ||
345 | 68..69 'x': u32 | ||
346 | 77..95 '{ loop...foo" }': &str | ||
347 | 79..86 'loop {}': ! | ||
348 | 84..86 '{}': () | ||
349 | 88..93 '"foo"': &str | ||
350 | 77..95: expected u32, got &str | ||
351 | 88..93: expected u32, got &str | ||
352 | "###); | ||
353 | } | ||
354 | |||
355 | #[test] | ||
356 | fn diverging_expression_3_break() { | ||
357 | let t = infer_with_mismatches( | ||
358 | r#" | ||
359 | //- /main.rs | ||
360 | fn test1() { | ||
361 | // should give type mismatch | ||
362 | let x: u32 = { loop { break; } }; | ||
363 | } | ||
364 | fn test2() { | ||
365 | // should give type mismatch | ||
366 | let x: u32 = { for a in b { break; }; }; | ||
367 | // should give type mismatch as well | ||
368 | let x: u32 = { for a in b {}; }; | ||
369 | // should give type mismatch as well | ||
370 | let x: u32 = { for a in b { return; }; }; | ||
371 | } | ||
372 | fn test3() { | ||
373 | // should give type mismatch | ||
374 | let x: u32 = { while true { break; }; }; | ||
375 | // should give type mismatch as well -- there's an implicit break, even if it's never hit | ||
376 | let x: u32 = { while true {}; }; | ||
377 | // should give type mismatch as well | ||
378 | let x: u32 = { while true { return; }; }; | ||
379 | } | ||
380 | "#, | ||
381 | true, | ||
382 | ); | ||
383 | assert_snapshot!(t, @r###" | ||
384 | 25..99 '{ ...} }; }': () | ||
385 | 68..69 'x': u32 | ||
386 | 77..96 '{ loop...k; } }': () | ||
387 | 79..94 'loop { break; }': () | ||
388 | 84..94 '{ break; }': () | ||
389 | 86..91 'break': ! | ||
390 | 77..96: expected u32, got () | ||
391 | 79..94: expected u32, got () | ||
392 | 111..357 '{ ...; }; }': () | ||
393 | 154..155 'x': u32 | ||
394 | 163..189 '{ for ...; }; }': () | ||
395 | 165..186 'for a ...eak; }': () | ||
396 | 169..170 'a': {unknown} | ||
397 | 174..175 'b': {unknown} | ||
398 | 176..186 '{ break; }': () | ||
399 | 178..183 'break': ! | ||
400 | 240..241 'x': u32 | ||
401 | 249..267 '{ for ... {}; }': () | ||
402 | 251..264 'for a in b {}': () | ||
403 | 255..256 'a': {unknown} | ||
404 | 260..261 'b': {unknown} | ||
405 | 262..264 '{}': () | ||
406 | 318..319 'x': u32 | ||
407 | 327..354 '{ for ...; }; }': () | ||
408 | 329..351 'for a ...urn; }': () | ||
409 | 333..334 'a': {unknown} | ||
410 | 338..339 'b': {unknown} | ||
411 | 340..351 '{ return; }': () | ||
412 | 342..348 'return': ! | ||
413 | 163..189: expected u32, got () | ||
414 | 249..267: expected u32, got () | ||
415 | 327..354: expected u32, got () | ||
416 | 369..668 '{ ...; }; }': () | ||
417 | 412..413 'x': u32 | ||
418 | 421..447 '{ whil...; }; }': () | ||
419 | 423..444 'while ...eak; }': () | ||
420 | 429..433 'true': bool | ||
421 | 434..444 '{ break; }': () | ||
422 | 436..441 'break': ! | ||
423 | 551..552 'x': u32 | ||
424 | 560..578 '{ whil... {}; }': () | ||
425 | 562..575 'while true {}': () | ||
426 | 568..572 'true': bool | ||
427 | 573..575 '{}': () | ||
428 | 629..630 'x': u32 | ||
429 | 638..665 '{ whil...; }; }': () | ||
430 | 640..662 'while ...urn; }': () | ||
431 | 646..650 'true': bool | ||
432 | 651..662 '{ return; }': () | ||
433 | 653..659 'return': ! | ||
434 | 421..447: expected u32, got () | ||
435 | 560..578: expected u32, got () | ||
436 | 638..665: expected u32, got () | ||
437 | "###); | ||
438 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index e17a17900..3820175f6 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -179,7 +179,7 @@ fn test(a: u32, b: isize, c: !, d: &str) { | |||
179 | 17..18 'b': isize | 179 | 17..18 'b': isize |
180 | 27..28 'c': ! | 180 | 27..28 'c': ! |
181 | 33..34 'd': &str | 181 | 33..34 'd': &str |
182 | 42..121 '{ ...f32; }': ! | 182 | 42..121 '{ ...f32; }': () |
183 | 48..49 'a': u32 | 183 | 48..49 'a': u32 |
184 | 55..56 'b': isize | 184 | 55..56 'b': isize |
185 | 62..63 'c': ! | 185 | 62..63 'c': ! |
@@ -935,7 +935,7 @@ fn foo() { | |||
935 | 29..33 'true': bool | 935 | 29..33 'true': bool |
936 | 34..51 '{ ... }': i32 | 936 | 34..51 '{ ... }': i32 |
937 | 44..45 '1': i32 | 937 | 44..45 '1': i32 |
938 | 57..80 '{ ... }': ! | 938 | 57..80 '{ ... }': i32 |
939 | 67..73 'return': ! | 939 | 67..73 'return': ! |
940 | 90..93 '_x2': i32 | 940 | 90..93 '_x2': i32 |
941 | 96..149 'if tru... }': i32 | 941 | 96..149 'if tru... }': i32 |
@@ -951,7 +951,7 @@ fn foo() { | |||
951 | 186..190 'true': bool | 951 | 186..190 'true': bool |
952 | 194..195 '3': i32 | 952 | 194..195 '3': i32 |
953 | 205..206 '_': bool | 953 | 205..206 '_': bool |
954 | 210..241 '{ ... }': ! | 954 | 210..241 '{ ... }': i32 |
955 | 224..230 'return': ! | 955 | 224..230 'return': ! |
956 | 257..260 '_x4': i32 | 956 | 257..260 '_x4': i32 |
957 | 263..320 'match ... }': i32 | 957 | 263..320 'match ... }': i32 |
@@ -1687,7 +1687,7 @@ fn foo() -> u32 { | |||
1687 | 17..59 '{ ...; }; }': () | 1687 | 17..59 '{ ...; }; }': () |
1688 | 27..28 'x': || -> usize | 1688 | 27..28 'x': || -> usize |
1689 | 31..56 '|| -> ...n 1; }': || -> usize | 1689 | 31..56 '|| -> ...n 1; }': || -> usize |
1690 | 43..56 '{ return 1; }': ! | 1690 | 43..56 '{ return 1; }': usize |
1691 | 45..53 'return 1': ! | 1691 | 45..53 'return 1': ! |
1692 | 52..53 '1': usize | 1692 | 52..53 '1': usize |
1693 | "### | 1693 | "### |
@@ -1706,7 +1706,7 @@ fn foo() -> u32 { | |||
1706 | 17..48 '{ ...; }; }': () | 1706 | 17..48 '{ ...; }; }': () |
1707 | 27..28 'x': || -> () | 1707 | 27..28 'x': || -> () |
1708 | 31..45 '|| { return; }': || -> () | 1708 | 31..45 '|| { return; }': || -> () |
1709 | 34..45 '{ return; }': ! | 1709 | 34..45 '{ return; }': () |
1710 | 36..42 'return': ! | 1710 | 36..42 'return': ! |
1711 | "### | 1711 | "### |
1712 | ); | 1712 | ); |