aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/infer.rs12
-rw-r--r--crates/ra_hir/src/ty/tests.rs63
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 171aead18..25dad81eb 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -263,7 +263,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
263 [17; 18) 'b': isize 263 [17; 18) 'b': isize
264 [27; 28) 'c': ! 264 [27; 28) 'c': !
265 [33; 34) 'd': &str 265 [33; 34) 'd': &str
266 [42; 121) '{ ...f32; }': () 266 [42; 121) '{ ...f32; }': !
267 [48; 49) 'a': u32 267 [48; 49) 'a': u32
268 [55; 56) 'b': isize 268 [55; 56) 'b': isize
269 [62; 63) 'c': ! 269 [62; 63) 'c': !
@@ -1026,6 +1026,67 @@ fn main(foo: Foo) {
1026} 1026}
1027 1027
1028#[test] 1028#[test]
1029fn infer_if_match_with_return() {
1030 assert_snapshot!(
1031 infer(r#"
1032fn foo() {
1033 let _x1 = if true {
1034 1
1035 } else {
1036 return;
1037 };
1038 let _x2 = if true {
1039 2
1040 } else {
1041 return
1042 };
1043 let _x3 = match true {
1044 true => 3,
1045 _ => {
1046 return;
1047 }
1048 };
1049 let _x4 = match true {
1050 true => 4,
1051 _ => return
1052 };
1053}"#),
1054 @r###"
1055 [10; 323) '{ ... }; }': ()
1056 [20; 23) '_x1': i32
1057 [26; 80) 'if tru... }': i32
1058 [29; 33) 'true': bool
1059 [34; 51) '{ ... }': i32
1060 [44; 45) '1': i32
1061 [57; 80) '{ ... }': !
1062 [67; 73) 'return': !
1063 [90; 93) '_x2': i32
1064 [96; 149) 'if tru... }': i32
1065 [99; 103) 'true': bool
1066 [104; 121) '{ ... }': i32
1067 [114; 115) '2': i32
1068 [127; 149) '{ ... }': !
1069 [137; 143) 'return': !
1070 [159; 162) '_x3': i32
1071 [165; 247) 'match ... }': i32
1072 [171; 175) 'true': bool
1073 [186; 190) 'true': bool
1074 [194; 195) '3': i32
1075 [205; 206) '_': bool
1076 [210; 241) '{ ... }': !
1077 [224; 230) 'return': !
1078 [257; 260) '_x4': i32
1079 [263; 320) 'match ... }': i32
1080 [269; 273) 'true': bool
1081 [284; 288) 'true': bool
1082 [292; 293) '4': i32
1083 [303; 304) '_': bool
1084 [308; 314) 'return': !
1085 "###
1086 )
1087}
1088
1089#[test]
1029fn infer_inherent_method() { 1090fn infer_inherent_method() {
1030 assert_snapshot!( 1091 assert_snapshot!(
1031 infer(r#" 1092 infer(r#"