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 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]
984fn infer_if_match_with_return() {
985 assert_snapshot!(
986 infer(r#"
987fn 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]
984fn infer_inherent_method() { 1045fn infer_inherent_method() {
985 assert_snapshot!( 1046 assert_snapshot!(
986 infer(r#" 1047 infer(r#"