diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 105 |
1 files changed, 82 insertions, 23 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index d94e8154b..812990426 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -280,8 +280,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
280 | let ty1 = self.resolve_ty_shallow(ty1); | 280 | let ty1 = self.resolve_ty_shallow(ty1); |
281 | let ty2 = self.resolve_ty_shallow(ty2); | 281 | let ty2 = self.resolve_ty_shallow(ty2); |
282 | match (&*ty1, &*ty2) { | 282 | match (&*ty1, &*ty2) { |
283 | (Ty::Unknown, ..) => true, | 283 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, |
284 | (.., Ty::Unknown) => true, | ||
285 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { | 284 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { |
286 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) | 285 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) |
287 | } | 286 | } |
@@ -976,24 +975,48 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
976 | ret_ty | 975 | ret_ty |
977 | } | 976 | } |
978 | 977 | ||
978 | /// This is similar to unify, but it makes the first type coerce to the | ||
979 | /// second one. | ||
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 | ||
984 | } else { | ||
985 | self.unify(from_ty, to_ty) | ||
986 | } | ||
987 | } | ||
988 | |||
979 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 989 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
990 | let ty = self.infer_expr_inner(tgt_expr, expected); | ||
991 | let could_unify = self.unify(&ty, &expected.ty); | ||
992 | if !could_unify { | ||
993 | self.result.type_mismatches.insert( | ||
994 | tgt_expr, | ||
995 | TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, | ||
996 | ); | ||
997 | } | ||
998 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
999 | ty | ||
1000 | } | ||
1001 | |||
1002 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | ||
980 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1003 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
981 | let ty = match &body[tgt_expr] { | 1004 | let ty = match &body[tgt_expr] { |
982 | Expr::Missing => Ty::Unknown, | 1005 | Expr::Missing => Ty::Unknown, |
983 | Expr::If { condition, then_branch, else_branch } => { | 1006 | Expr::If { condition, then_branch, else_branch } => { |
984 | // 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 |
985 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 1008 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
986 | let then_ty = self.infer_expr(*then_branch, expected); | 1009 | |
987 | match else_branch { | 1010 | let then_ty = self.infer_expr_inner(*then_branch, &expected); |
988 | Some(else_branch) => { | 1011 | self.coerce(&then_ty, &expected.ty); |
989 | self.infer_expr(*else_branch, expected); | 1012 | |
990 | } | 1013 | let else_ty = match else_branch { |
991 | None => { | 1014 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
992 | // no else branch -> unit | 1015 | None => Ty::unit(), |
993 | self.unify(&then_ty, &Ty::unit()); // actually coerce | ||
994 | } | ||
995 | }; | 1016 | }; |
996 | then_ty | 1017 | self.coerce(&else_ty, &expected.ty); |
1018 | |||
1019 | expected.ty.clone() | ||
997 | } | 1020 | } |
998 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 1021 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), |
999 | Expr::TryBlock { body } => { | 1022 | Expr::TryBlock { body } => { |
@@ -1073,12 +1096,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1073 | Expr::MethodCall { receiver, args, method_name, generic_args } => self | 1096 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
1074 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), | 1097 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
1075 | Expr::Match { expr, arms } => { | 1098 | Expr::Match { expr, arms } => { |
1099 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | ||
1076 | let expected = if expected.ty == Ty::Unknown { | 1100 | let expected = if expected.ty == Ty::Unknown { |
1077 | Expectation::has_type(self.new_type_var()) | 1101 | Expectation::has_type(self.new_type_var()) |
1078 | } else { | 1102 | } else { |
1079 | expected.clone() | 1103 | expected.clone() |
1080 | }; | 1104 | }; |
1081 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 1105 | |
1106 | let mut arm_tys = Vec::with_capacity(arms.len()); | ||
1082 | 1107 | ||
1083 | for arm in arms { | 1108 | for arm in arms { |
1084 | for &pat in &arm.pats { | 1109 | for &pat in &arm.pats { |
@@ -1090,10 +1115,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1090 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 1115 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), |
1091 | ); | 1116 | ); |
1092 | } | 1117 | } |
1093 | self.infer_expr(arm.expr, &expected); | 1118 | arm_tys.push(self.infer_expr_inner(arm.expr, &expected)); |
1119 | } | ||
1120 | |||
1121 | let lub_ty = calculate_least_upper_bound(expected.ty.clone(), &arm_tys); | ||
1122 | |||
1123 | for arm_ty in &arm_tys { | ||
1124 | self.coerce(arm_ty, &lub_ty); | ||
1094 | } | 1125 | } |
1095 | 1126 | ||
1096 | expected.ty | 1127 | lub_ty |
1097 | } | 1128 | } |
1098 | Expr::Path(p) => { | 1129 | Expr::Path(p) => { |
1099 | // FIXME this could be more efficient... | 1130 | // FIXME this could be more efficient... |
@@ -1356,15 +1387,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1356 | }; | 1387 | }; |
1357 | // use a new type variable if we got Ty::Unknown here | 1388 | // use a new type variable if we got Ty::Unknown here |
1358 | let ty = self.insert_type_vars_shallow(ty); | 1389 | let ty = self.insert_type_vars_shallow(ty); |
1359 | let could_unify = self.unify(&ty, &expected.ty); | ||
1360 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | 1390 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); |
1361 | self.write_expr_ty(tgt_expr, ty.clone()); | 1391 | self.write_expr_ty(tgt_expr, ty.clone()); |
1362 | if !could_unify { | ||
1363 | self.result.type_mismatches.insert( | ||
1364 | tgt_expr, | ||
1365 | TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, | ||
1366 | ); | ||
1367 | } | ||
1368 | ty | 1392 | ty |
1369 | } | 1393 | } |
1370 | 1394 | ||
@@ -1394,7 +1418,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1394 | } | 1418 | } |
1395 | } | 1419 | } |
1396 | } | 1420 | } |
1397 | let ty = if let Some(expr) = tail { self.infer_expr(expr, expected) } else { Ty::unit() }; | 1421 | let ty = |
1422 | if let Some(expr) = tail { self.infer_expr_inner(expr, expected) } else { Ty::unit() }; | ||
1398 | ty | 1423 | ty |
1399 | } | 1424 | } |
1400 | 1425 | ||
@@ -1616,3 +1641,37 @@ mod diagnostics { | |||
1616 | } | 1641 | } |
1617 | } | 1642 | } |
1618 | } | 1643 | } |
1644 | |||
1645 | fn is_never(ty: &Ty) -> bool { | ||
1646 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty { | ||
1647 | true | ||
1648 | } else { | ||
1649 | false | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | fn calculate_least_upper_bound(expected_ty: Ty, actual_tys: &[Ty]) -> Ty { | ||
1654 | let mut all_never = true; | ||
1655 | let mut last_never_ty = None; | ||
1656 | let mut least_upper_bound = expected_ty; | ||
1657 | |||
1658 | for actual_ty in actual_tys { | ||
1659 | if is_never(actual_ty) { | ||
1660 | last_never_ty = Some(actual_ty.clone()); | ||
1661 | } else { | ||
1662 | all_never = false; | ||
1663 | least_upper_bound = match (actual_ty, &least_upper_bound) { | ||
1664 | (_, Ty::Unknown) | ||
1665 | | (Ty::Infer(_), Ty::Infer(InferTy::TypeVar(_))) | ||
1666 | | (Ty::Apply(_), _) => actual_ty.clone(), | ||
1667 | _ => least_upper_bound, | ||
1668 | } | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | if all_never && last_never_ty.is_some() { | ||
1673 | last_never_ty.unwrap() | ||
1674 | } else { | ||
1675 | least_upper_bound | ||
1676 | } | ||
1677 | } | ||