aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty/infer.rs91
-rw-r--r--crates/ra_hir/src/ty/tests.rs58
2 files changed, 98 insertions, 51 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 3911695df..074baa8ef 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -296,9 +296,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
296 | (Ty::Infer(InferTy::IntVar(tv)), other) 296 | (Ty::Infer(InferTy::IntVar(tv)), other)
297 | (other, Ty::Infer(InferTy::IntVar(tv))) 297 | (other, Ty::Infer(InferTy::IntVar(tv)))
298 | (Ty::Infer(InferTy::FloatVar(tv)), other) 298 | (Ty::Infer(InferTy::FloatVar(tv)), other)
299 | (other, Ty::Infer(InferTy::FloatVar(tv))) 299 | (other, Ty::Infer(InferTy::FloatVar(tv))) => {
300 if !is_never(other) =>
301 {
302 // the type var is unknown since we tried to resolve it 300 // the type var is unknown since we tried to resolve it
303 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); 301 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
304 true 302 true
@@ -977,27 +975,56 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
977 ret_ty 975 ret_ty
978 } 976 }
979 977
978 fn coerce(&mut self, tgt_expr: ExprId, ty1: Ty, ty2: Ty) -> Ty {
979 if is_never(&ty1) {
980 ty2
981 } else {
982 self.unify(&ty1, &ty2);
983 // TODO Fugly and looks like we need more, `infer_adt_pattern` and other fails
984 let ty = self.resolve_ty_as_possible(&mut vec![], ty1);
985 self.write_expr_ty(tgt_expr, ty.clone());
986 ty
987 }
988 }
989
980 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 990 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
991 let ty = self.infer_expr_inner(tgt_expr, expected);
992 // use a new type variable if we got Ty::Unknown here
993 let ty = self.insert_type_vars_shallow(ty);
994 let could_unify = self.unify(&ty, &expected.ty);
995 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
996 self.write_expr_ty(tgt_expr, ty.clone());
997 if !could_unify {
998 self.result.type_mismatches.insert(
999 tgt_expr,
1000 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
1001 );
1002 }
1003 ty
1004 }
1005
1006 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
981 let body = Arc::clone(&self.body); // avoid borrow checker problem 1007 let body = Arc::clone(&self.body); // avoid borrow checker problem
982 let ty = match &body[tgt_expr] { 1008 match &body[tgt_expr] {
983 Expr::Missing => Ty::Unknown, 1009 Expr::Missing => Ty::Unknown,
984 Expr::If { condition, then_branch, else_branch } => { 1010 Expr::If { condition, then_branch, else_branch } => {
985 // if let is desugared to match, so this is always simple if 1011 // if let is desugared to match, so this is always simple if
986 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 1012 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
987 1013
988 let mut branch_tys = Vec::with_capacity(2); 1014 let then_ty = self.infer_expr_inner(*then_branch, &expected);
989 let then_ty = self.infer_expr(*then_branch, &expected); 1015 self.coerce(*then_branch, then_ty.clone(), expected.ty.clone());
990 match else_branch { 1016 match else_branch {
991 Some(else_branch) => { 1017 Some(else_branch) => {
992 branch_tys.push(self.infer_expr(*else_branch, &expected)); 1018 let else_ty = self.infer_expr_inner(*else_branch, &expected);
1019 self.coerce(*else_branch, else_ty, expected.ty.clone());
993 } 1020 }
994 None => { 1021 None => {
995 // no else branch -> unit 1022 // no else branch -> unit
996 self.unify(&then_ty, &Ty::unit()); // actually coerce 1023 self.unify(&then_ty, &Ty::unit()); // actually coerce
997 } 1024 }
998 }; 1025 };
999 branch_tys.push(then_ty); 1026
1000 calculate_least_upper_bound(expected.ty.clone(), branch_tys) 1027 expected.ty.clone()
1001 } 1028 }
1002 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), 1029 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
1003 Expr::TryBlock { body } => { 1030 Expr::TryBlock { body } => {
@@ -1084,8 +1111,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1084 expected.clone() 1111 expected.clone()
1085 }; 1112 };
1086 1113
1087 let mut arm_tys = Vec::with_capacity(arms.len());
1088
1089 for arm in arms { 1114 for arm in arms {
1090 for &pat in &arm.pats { 1115 for &pat in &arm.pats {
1091 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); 1116 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default());
@@ -1096,9 +1121,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1096 &Expectation::has_type(Ty::simple(TypeCtor::Bool)), 1121 &Expectation::has_type(Ty::simple(TypeCtor::Bool)),
1097 ); 1122 );
1098 } 1123 }
1099 arm_tys.push(self.infer_expr(arm.expr, &expected)); 1124 let match_arm_ty = self.infer_expr_inner(arm.expr, &expected);
1125 self.coerce(arm.expr, match_arm_ty, expected.ty.clone());
1100 } 1126 }
1101 calculate_least_upper_bound(expected.ty.clone(), arm_tys) 1127
1128 expected.ty
1102 } 1129 }
1103 Expr::Path(p) => { 1130 Expr::Path(p) => {
1104 // FIXME this could be more efficient... 1131 // FIXME this could be more efficient...
@@ -1358,19 +1385,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1358 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)), 1385 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)),
1359 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)), 1386 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)),
1360 }, 1387 },
1361 };
1362 // use a new type variable if we got Ty::Unknown here
1363 let ty = self.insert_type_vars_shallow(ty);
1364 let could_unify = self.unify(&ty, &expected.ty);
1365 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
1366 self.write_expr_ty(tgt_expr, ty.clone());
1367 if !could_unify {
1368 self.result.type_mismatches.insert(
1369 tgt_expr,
1370 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
1371 );
1372 } 1388 }
1373 ty
1374 } 1389 }
1375 1390
1376 fn infer_block( 1391 fn infer_block(
@@ -1629,29 +1644,3 @@ fn is_never(ty: &Ty) -> bool {
1629 false 1644 false
1630 } 1645 }
1631} 1646}
1632
1633fn calculate_least_upper_bound(expected_ty: Ty, actual_tys: Vec<Ty>) -> Ty {
1634 let mut all_never = true;
1635 let mut last_never_ty = None;
1636 let mut least_upper_bound = expected_ty;
1637
1638 for actual_ty in actual_tys {
1639 if is_never(&actual_ty) {
1640 last_never_ty = Some(actual_ty);
1641 } else {
1642 all_never = false;
1643 least_upper_bound = match (&actual_ty, &least_upper_bound) {
1644 (_, Ty::Unknown)
1645 | (Ty::Infer(_), Ty::Infer(InferTy::TypeVar(_)))
1646 | (Ty::Apply(_), _) => actual_ty,
1647 _ => least_upper_bound,
1648 }
1649 }
1650 }
1651
1652 if all_never && last_never_ty.is_some() {
1653 last_never_ty.unwrap()
1654 } else {
1655 least_upper_bound
1656 }
1657}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index a30a645eb..4fa9d131d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3619,6 +3619,26 @@ fn test(a: i32) {
3619 } 3619 }
3620 3620
3621 #[test] 3621 #[test]
3622 fn match_second_block_arm_never() {
3623 let t = type_at(
3624 r#"
3625//- /main.rs
3626fn test(a: i32) {
3627 let i = match a {
3628 1 => { 3.0 },
3629 2 => { loop {} },
3630 3 => { 3.0 },
3631 _ => { return },
3632 };
3633 i<|>
3634 ()
3635}
3636"#,
3637 );
3638 assert_eq!(t, "f64");
3639 }
3640
3641 #[test]
3622 fn if_never() { 3642 fn if_never() {
3623 let t = type_at( 3643 let t = type_at(
3624 r#" 3644 r#"
@@ -3657,6 +3677,26 @@ fn test(input: bool) {
3657 } 3677 }
3658 3678
3659 #[test] 3679 #[test]
3680 fn match_first_block_arm_never() {
3681 let t = type_at(
3682 r#"
3683//- /main.rs
3684fn test(a: i32) {
3685 let i = match a {
3686 1 => { return },
3687 2 => { 2.0 },
3688 3 => { loop {} },
3689 _ => { 3.0 },
3690 };
3691 i<|>
3692 ()
3693}
3694"#,
3695 );
3696 assert_eq!(t, "f64");
3697 }
3698
3699 #[test]
3660 fn match_second_arm_never() { 3700 fn match_second_arm_never() {
3661 let t = type_at( 3701 let t = type_at(
3662 r#" 3702 r#"
@@ -3695,6 +3735,24 @@ fn test(a: i32) {
3695 } 3735 }
3696 3736
3697 #[test] 3737 #[test]
3738 fn match_all_block_arms_never() {
3739 let t = type_at(
3740 r#"
3741//- /main.rs
3742fn test(a: i32) {
3743 let i = match a {
3744 2 => { return },
3745 _ => { loop {} },
3746 };
3747 i<|>
3748 ()
3749}
3750"#,
3751 );
3752 assert_eq!(t, "!");
3753 }
3754
3755 #[test]
3698 fn match_no_never_arms() { 3756 fn match_no_never_arms() {
3699 let t = type_at( 3757 let t = type_at(
3700 r#" 3758 r#"