diff options
author | Kirill Bulatov <[email protected]> | 2019-08-21 22:34:50 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2019-08-26 20:44:50 +0100 |
commit | 44386d5373114ffc88ef6bd182fb3b58a7c27e69 (patch) | |
tree | 19a1d277377ecf2ea9c5ca9232f019d20b53137d /crates/ra_hir/src/ty | |
parent | 89f3cc587d07a3cdcebf84cc4b99fe42636e66f0 (diff) |
An attempt to add the coercion logic for Never
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 91 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 58 |
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 | |||
1633 | fn 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 | ||
3626 | fn 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 | ||
3684 | fn 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 | ||
3742 | fn 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#" |