aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/ty/infer.rs74
-rw-r--r--crates/ra_hir/src/ty/tests.rs22
2 files changed, 66 insertions, 30 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 074baa8ef..0aa993067 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -975,48 +975,44 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
975 ret_ty 975 ret_ty
976 } 976 }
977 977
978 fn coerce(&mut self, tgt_expr: ExprId, ty1: Ty, ty2: Ty) -> Ty { 978 /// This is similar to unify, but it makes the first type coerce to the
979 if is_never(&ty1) { 979 /// second one.
980 ty2 980 fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool {
981 if is_never(from_ty) {
982 // ! coerces to any type
983 true
981 } else { 984 } else {
982 self.unify(&ty1, &ty2); 985 self.unify(from_ty, to_ty)
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 } 986 }
988 } 987 }
989 988
990 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 989 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
991 let ty = self.infer_expr_inner(tgt_expr, expected); 990 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); 991 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 { 992 if !could_unify {
998 self.result.type_mismatches.insert( 993 self.result.type_mismatches.insert(
999 tgt_expr, 994 tgt_expr,
1000 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 995 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
1001 ); 996 );
1002 } 997 }
998 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
1003 ty 999 ty
1004 } 1000 }
1005 1001
1006 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 1002 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
1007 let body = Arc::clone(&self.body); // avoid borrow checker problem 1003 let body = Arc::clone(&self.body); // avoid borrow checker problem
1008 match &body[tgt_expr] { 1004 let ty = match &body[tgt_expr] {
1009 Expr::Missing => Ty::Unknown, 1005 Expr::Missing => Ty::Unknown,
1010 Expr::If { condition, then_branch, else_branch } => { 1006 Expr::If { condition, then_branch, else_branch } => {
1011 // if let is desugared to match, so this is always simple if 1007 // if let is desugared to match, so this is always simple if
1012 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 1008 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
1013 1009
1014 let then_ty = self.infer_expr_inner(*then_branch, &expected); 1010 let then_ty = self.infer_expr_inner(*then_branch, &expected);
1015 self.coerce(*then_branch, then_ty.clone(), expected.ty.clone()); 1011 self.coerce(&then_ty, &expected.ty);
1016 match else_branch { 1012 match else_branch {
1017 Some(else_branch) => { 1013 Some(else_branch) => {
1018 let else_ty = self.infer_expr_inner(*else_branch, &expected); 1014 let else_ty = self.infer_expr_inner(*else_branch, &expected);
1019 self.coerce(*else_branch, else_ty, expected.ty.clone()); 1015 self.coerce(&else_ty, &expected.ty);
1020 } 1016 }
1021 None => { 1017 None => {
1022 // no else branch -> unit 1018 // no else branch -> unit
@@ -1111,6 +1107,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1111 expected.clone() 1107 expected.clone()
1112 }; 1108 };
1113 1109
1110 let mut arm_tys = Vec::with_capacity(arms.len());
1111
1114 for arm in arms { 1112 for arm in arms {
1115 for &pat in &arm.pats { 1113 for &pat in &arm.pats {
1116 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); 1114 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default());
@@ -1121,11 +1119,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1121 &Expectation::has_type(Ty::simple(TypeCtor::Bool)), 1119 &Expectation::has_type(Ty::simple(TypeCtor::Bool)),
1122 ); 1120 );
1123 } 1121 }
1124 let match_arm_ty = self.infer_expr_inner(arm.expr, &expected); 1122 arm_tys.push(self.infer_expr_inner(arm.expr, &expected));
1125 self.coerce(arm.expr, match_arm_ty, expected.ty.clone());
1126 } 1123 }
1127 1124
1128 expected.ty 1125 let lub_ty = calculate_least_upper_bound(expected.ty.clone(), &arm_tys);
1126
1127 for arm_ty in &arm_tys {
1128 self.coerce(arm_ty, &lub_ty);
1129 }
1130
1131 lub_ty
1129 } 1132 }
1130 Expr::Path(p) => { 1133 Expr::Path(p) => {
1131 // FIXME this could be more efficient... 1134 // FIXME this could be more efficient...
@@ -1385,7 +1388,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1385 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)), 1388 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int(*ty)),
1386 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)), 1389 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float(*ty)),
1387 }, 1390 },
1388 } 1391 };
1392 // use a new type variable if we got Ty::Unknown here
1393 let ty = self.insert_type_vars_shallow(ty);
1394 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
1395 self.write_expr_ty(tgt_expr, ty.clone());
1396 ty
1389 } 1397 }
1390 1398
1391 fn infer_block( 1399 fn infer_block(
@@ -1414,7 +1422,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1414 } 1422 }
1415 } 1423 }
1416 } 1424 }
1417 let ty = if let Some(expr) = tail { self.infer_expr(expr, expected) } else { Ty::unit() }; 1425 let ty = if let Some(expr) = tail { self.infer_expr_inner(expr, expected) } else { Ty::unit() };
1418 ty 1426 ty
1419 } 1427 }
1420 1428
@@ -1644,3 +1652,29 @@ fn is_never(ty: &Ty) -> bool {
1644 false 1652 false
1645 } 1653 }
1646} 1654}
1655
1656fn calculate_least_upper_bound(expected_ty: Ty, actual_tys: &[Ty]) -> Ty {
1657 let mut all_never = true;
1658 let mut last_never_ty = None;
1659 let mut least_upper_bound = expected_ty;
1660
1661 for actual_ty in actual_tys {
1662 if is_never(actual_ty) {
1663 last_never_ty = Some(actual_ty.clone());
1664 } else {
1665 all_never = false;
1666 least_upper_bound = match (actual_ty, &least_upper_bound) {
1667 (_, Ty::Unknown)
1668 | (Ty::Infer(_), Ty::Infer(InferTy::TypeVar(_)))
1669 | (Ty::Apply(_), _) => actual_ty.clone(),
1670 _ => least_upper_bound,
1671 }
1672 }
1673 }
1674
1675 if all_never && last_never_ty.is_some() {
1676 last_never_ty.unwrap()
1677 } else {
1678 least_upper_bound
1679 }
1680}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4fa9d131d..7fc9fbb63 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -718,16 +718,18 @@ fn main(foo: Foo) {
718} 718}
719"#), 719"#),
720 @r###" 720 @r###"
721[35; 38) 'foo': Foo 721
722[45; 109) '{ ... } }': () 722 ⋮[35; 38) 'foo': Foo
723[51; 107) 'if tru... }': () 723 ⋮[45; 109) '{ ... } }': ()
724[54; 58) 'true': bool 724 ⋮[51; 107) 'if tru... }': ()
725[59; 67) '{ }': () 725 ⋮[54; 58) 'true': bool
726[73; 107) 'if fal... }': i32 726 ⋮[59; 67) '{ }': ()
727[76; 81) 'false': bool 727 ⋮[73; 107) 'if fal... }': ()
728[82; 107) '{ ... }': i32 728 ⋮[76; 81) 'false': bool
729[92; 95) 'foo': Foo 729 ⋮[82; 107) '{ ... }': i32
730[92; 101) 'foo.field': i32"### 730 ⋮[92; 95) 'foo': Foo
731 ⋮[92; 101) 'foo.field': i32
732 "###
731 ) 733 )
732} 734}
733 735