diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-10-02 19:57:20 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-10-02 19:57:20 +0100 |
commit | e1c367595139f109fb6f53811bed7d67a384793e (patch) | |
tree | afcdff55850259d9253af48ec63c236afcda1d7f /crates/ra_hir | |
parent | ba3ec8b1508e6f07159fd78ed569bbf47e9936ba (diff) | |
parent | f491567fb30b0956b3a0a90ed43099953a3e732a (diff) |
Merge #1945
1945: Handle divergence in type inference for blocks r=flodiebold a=lnicola
Fixes #1944.
The `infer_basics` test is failing, not sure what to do about it.
Co-authored-by: Laurențiu Nicola <[email protected]>
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 63 |
2 files changed, 72 insertions, 3 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 2e4a489a0..ca9aefc42 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -1602,6 +1602,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1602 | tail: Option<ExprId>, | 1602 | tail: Option<ExprId>, |
1603 | expected: &Expectation, | 1603 | expected: &Expectation, |
1604 | ) -> Ty { | 1604 | ) -> Ty { |
1605 | let mut diverges = false; | ||
1605 | for stmt in statements { | 1606 | for stmt in statements { |
1606 | match stmt { | 1607 | match stmt { |
1607 | Statement::Let { pat, type_ref, initializer } => { | 1608 | Statement::Let { pat, type_ref, initializer } => { |
@@ -1623,16 +1624,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1623 | self.infer_pat(*pat, &ty, BindingMode::default()); | 1624 | self.infer_pat(*pat, &ty, BindingMode::default()); |
1624 | } | 1625 | } |
1625 | Statement::Expr(expr) => { | 1626 | Statement::Expr(expr) => { |
1626 | self.infer_expr(*expr, &Expectation::none()); | 1627 | if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) { |
1628 | diverges = true; | ||
1629 | } | ||
1627 | } | 1630 | } |
1628 | } | 1631 | } |
1629 | } | 1632 | } |
1630 | 1633 | ||
1631 | if let Some(expr) = tail { | 1634 | let ty = if let Some(expr) = tail { |
1632 | self.infer_expr_coerce(expr, expected) | 1635 | self.infer_expr_coerce(expr, expected) |
1633 | } else { | 1636 | } else { |
1634 | self.coerce(&Ty::unit(), &expected.ty); | 1637 | self.coerce(&Ty::unit(), &expected.ty); |
1635 | Ty::unit() | 1638 | Ty::unit() |
1639 | }; | ||
1640 | if diverges { | ||
1641 | Ty::simple(TypeCtor::Never) | ||
1642 | } else { | ||
1643 | ty | ||
1636 | } | 1644 | } |
1637 | } | 1645 | } |
1638 | 1646 | ||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 4df39c191..66f63ca24 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -218,7 +218,7 @@ fn test(a: u32, b: isize, c: !, d: &str) { | |||
218 | [17; 18) 'b': isize | 218 | [17; 18) 'b': isize |
219 | [27; 28) 'c': ! | 219 | [27; 28) 'c': ! |
220 | [33; 34) 'd': &str | 220 | [33; 34) 'd': &str |
221 | [42; 121) '{ ...f32; }': () | 221 | [42; 121) '{ ...f32; }': ! |
222 | [48; 49) 'a': u32 | 222 | [48; 49) 'a': u32 |
223 | [55; 56) 'b': isize | 223 | [55; 56) 'b': isize |
224 | [62; 63) 'c': ! | 224 | [62; 63) 'c': ! |
@@ -981,6 +981,67 @@ fn main(foo: Foo) { | |||
981 | } | 981 | } |
982 | 982 | ||
983 | #[test] | 983 | #[test] |
984 | fn infer_if_match_with_return() { | ||
985 | assert_snapshot!( | ||
986 | infer(r#" | ||
987 | fn foo() { | ||
988 | let _x1 = if true { | ||
989 | 1 | ||
990 | } else { | ||
991 | return; | ||
992 | }; | ||
993 | let _x2 = if true { | ||
994 | 2 | ||
995 | } else { | ||
996 | return | ||
997 | }; | ||
998 | let _x3 = match true { | ||
999 | true => 3, | ||
1000 | _ => { | ||
1001 | return; | ||
1002 | } | ||
1003 | }; | ||
1004 | let _x4 = match true { | ||
1005 | true => 4, | ||
1006 | _ => return | ||
1007 | }; | ||
1008 | }"#), | ||
1009 | @r###" | ||
1010 | [10; 323) '{ ... }; }': () | ||
1011 | [20; 23) '_x1': i32 | ||
1012 | [26; 80) 'if tru... }': i32 | ||
1013 | [29; 33) 'true': bool | ||
1014 | [34; 51) '{ ... }': i32 | ||
1015 | [44; 45) '1': i32 | ||
1016 | [57; 80) '{ ... }': ! | ||
1017 | [67; 73) 'return': ! | ||
1018 | [90; 93) '_x2': i32 | ||
1019 | [96; 149) 'if tru... }': i32 | ||
1020 | [99; 103) 'true': bool | ||
1021 | [104; 121) '{ ... }': i32 | ||
1022 | [114; 115) '2': i32 | ||
1023 | [127; 149) '{ ... }': ! | ||
1024 | [137; 143) 'return': ! | ||
1025 | [159; 162) '_x3': i32 | ||
1026 | [165; 247) 'match ... }': i32 | ||
1027 | [171; 175) 'true': bool | ||
1028 | [186; 190) 'true': bool | ||
1029 | [194; 195) '3': i32 | ||
1030 | [205; 206) '_': bool | ||
1031 | [210; 241) '{ ... }': ! | ||
1032 | [224; 230) 'return': ! | ||
1033 | [257; 260) '_x4': i32 | ||
1034 | [263; 320) 'match ... }': i32 | ||
1035 | [269; 273) 'true': bool | ||
1036 | [284; 288) 'true': bool | ||
1037 | [292; 293) '4': i32 | ||
1038 | [303; 304) '_': bool | ||
1039 | [308; 314) 'return': ! | ||
1040 | "### | ||
1041 | ) | ||
1042 | } | ||
1043 | |||
1044 | #[test] | ||
984 | fn infer_inherent_method() { | 1045 | fn infer_inherent_method() { |
985 | assert_snapshot!( | 1046 | assert_snapshot!( |
986 | infer(r#" | 1047 | infer(r#" |