diff options
author | Florian Diebold <[email protected]> | 2019-08-26 19:12:41 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2019-08-26 20:44:50 +0100 |
commit | e37b6c58378355347898cbdf1eef278137f6b461 (patch) | |
tree | f6390e1488d486133addff8f51b9b2ecd4b042af /crates/ra_hir/src/ty | |
parent | 44386d5373114ffc88ef6bd182fb3b58a7c27e69 (diff) |
Make infer_block not unify; add back calculate_least_upper_bound
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 74 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 22 |
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 | |||
1656 | fn 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 | ||