aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2019-08-15 21:53:42 +0100
committerKirill Bulatov <[email protected]>2019-08-26 20:44:50 +0100
commit89f3cc587d07a3cdcebf84cc4b99fe42636e66f0 (patch)
tree7cb5af59ad096a42bcdf85aea0662fb7bebd1965 /crates/ra_hir/src
parent8b612251fd8c741416d2fb320bd908b76134fde5 (diff)
Properly coerce never types
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/marks.rs6
-rw-r--r--crates/ra_hir/src/ty/infer.rs90
-rw-r--r--crates/ra_hir/src/ty/tests.rs7
3 files changed, 46 insertions, 57 deletions
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index f450aef9f..5b15eee90 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -11,10 +11,4 @@ test_utils::marks!(
11 match_ergonomics_ref 11 match_ergonomics_ref
12 trait_resolution_on_fn_type 12 trait_resolution_on_fn_type
13 infer_while_let 13 infer_while_let
14 match_first_arm_never
15 match_second_arm_never
16 match_all_arms_never
17 match_no_never_arms
18 if_never
19 if_else_never
20); 14);
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 7b59ebfe7..3911695df 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -297,7 +297,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
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 !Self::is_never(other) => 300 if !is_never(other) =>
301 { 301 {
302 // the type var is unknown since we tried to resolve it 302 // the type var is unknown since we tried to resolve it
303 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); 303 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
@@ -984,24 +984,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
984 Expr::If { condition, then_branch, else_branch } => { 984 Expr::If { condition, then_branch, else_branch } => {
985 // if let is desugared to match, so this is always simple if 985 // if let is desugared to match, so this is always simple if
986 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 986 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
987 let then_ty = self.infer_expr(*then_branch, expected); 987
988 let mut branch_tys = Vec::with_capacity(2);
989 let then_ty = self.infer_expr(*then_branch, &expected);
988 match else_branch { 990 match else_branch {
989 Some(else_branch) => { 991 Some(else_branch) => {
990 let else_ty = self.infer_expr(*else_branch, expected); 992 branch_tys.push(self.infer_expr(*else_branch, &expected));
991 if Self::is_never(&then_ty) {
992 tested_by!(if_never);
993 else_ty
994 } else {
995 tested_by!(if_else_never);
996 then_ty
997 }
998 } 993 }
999 None => { 994 None => {
1000 // no else branch -> unit 995 // no else branch -> unit
1001 self.unify(&then_ty, &Ty::unit()); // actually coerce 996 self.unify(&then_ty, &Ty::unit()); // actually coerce
1002 then_ty
1003 } 997 }
1004 } 998 };
999 branch_tys.push(then_ty);
1000 calculate_least_upper_bound(expected.ty.clone(), branch_tys)
1005 } 1001 }
1006 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), 1002 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
1007 Expr::TryBlock { body } => { 1003 Expr::TryBlock { body } => {
@@ -1081,15 +1077,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1081 Expr::MethodCall { receiver, args, method_name, generic_args } => self 1077 Expr::MethodCall { receiver, args, method_name, generic_args } => self
1082 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 1078 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()),
1083 Expr::Match { expr, arms } => { 1079 Expr::Match { expr, arms } => {
1080 let input_ty = self.infer_expr(*expr, &Expectation::none());
1084 let expected = if expected.ty == Ty::Unknown { 1081 let expected = if expected.ty == Ty::Unknown {
1085 Expectation::has_type(self.new_type_var()) 1082 Expectation::has_type(self.new_type_var())
1086 } else { 1083 } else {
1087 expected.clone() 1084 expected.clone()
1088 }; 1085 };
1089 let input_ty = self.infer_expr(*expr, &Expectation::none());
1090 1086
1091 let mut resulting_match_ty = None; 1087 let mut arm_tys = Vec::with_capacity(arms.len());
1092 let mut all_arms_never = !arms.is_empty();
1093 1088
1094 for arm in arms { 1089 for arm in arms {
1095 for &pat in &arm.pats { 1090 for &pat in &arm.pats {
@@ -1101,28 +1096,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1101 &Expectation::has_type(Ty::simple(TypeCtor::Bool)), 1096 &Expectation::has_type(Ty::simple(TypeCtor::Bool)),
1102 ); 1097 );
1103 } 1098 }
1104 let arm_ty = self.infer_expr(arm.expr, &expected); 1099 arm_tys.push(self.infer_expr(arm.expr, &expected));
1105 if all_arms_never && Self::is_never(&arm_ty) {
1106 tested_by!(match_first_arm_never);
1107 resulting_match_ty = Some(arm_ty);
1108 } else {
1109 tested_by!(match_second_arm_never);
1110 all_arms_never = false;
1111 resulting_match_ty = None;
1112 }
1113 }
1114
1115 if let (Ty::Infer(expected_tv), Some(match_ty)) =
1116 (&expected.ty, &resulting_match_ty)
1117 {
1118 tested_by!(match_all_arms_never);
1119 self.var_unification_table
1120 .union_value(expected_tv.to_inner(), TypeVarValue::Known(match_ty.clone()));
1121 match_ty.clone()
1122 } else {
1123 tested_by!(match_no_never_arms);
1124 expected.ty
1125 } 1100 }
1101 calculate_least_upper_bound(expected.ty.clone(), arm_tys)
1126 } 1102 }
1127 Expr::Path(p) => { 1103 Expr::Path(p) => {
1128 // FIXME this could be more efficient... 1104 // FIXME this could be more efficient...
@@ -1397,14 +1373,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1397 ty 1373 ty
1398 } 1374 }
1399 1375
1400 fn is_never(ty: &Ty) -> bool {
1401 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty {
1402 true
1403 } else {
1404 false
1405 }
1406 }
1407
1408 fn infer_block( 1376 fn infer_block(
1409 &mut self, 1377 &mut self,
1410 statements: &[Statement], 1378 statements: &[Statement],
@@ -1653,3 +1621,37 @@ mod diagnostics {
1653 } 1621 }
1654 } 1622 }
1655} 1623}
1624
1625fn is_never(ty: &Ty) -> bool {
1626 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty {
1627 true
1628 } else {
1629 false
1630 }
1631}
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 195514f10..a30a645eb 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3597,11 +3597,9 @@ fn no_such_field_diagnostics() {
3597 3597
3598mod branching_with_never_tests { 3598mod branching_with_never_tests {
3599 use super::type_at; 3599 use super::type_at;
3600 use test_utils::covers;
3601 3600
3602 #[test] 3601 #[test]
3603 fn match_first_arm_never() { 3602 fn match_first_arm_never() {
3604 covers!(match_first_arm_never);
3605 let t = type_at( 3603 let t = type_at(
3606 r#" 3604 r#"
3607//- /main.rs 3605//- /main.rs
@@ -3622,7 +3620,6 @@ fn test(a: i32) {
3622 3620
3623 #[test] 3621 #[test]
3624 fn if_never() { 3622 fn if_never() {
3625 covers!(if_never);
3626 let t = type_at( 3623 let t = type_at(
3627 r#" 3624 r#"
3628//- /main.rs 3625//- /main.rs
@@ -3642,7 +3639,6 @@ fn test() {
3642 3639
3643 #[test] 3640 #[test]
3644 fn if_else_never() { 3641 fn if_else_never() {
3645 covers!(if_else_never);
3646 let t = type_at( 3642 let t = type_at(
3647 r#" 3643 r#"
3648//- /main.rs 3644//- /main.rs
@@ -3662,7 +3658,6 @@ fn test(input: bool) {
3662 3658
3663 #[test] 3659 #[test]
3664 fn match_second_arm_never() { 3660 fn match_second_arm_never() {
3665 covers!(match_second_arm_never);
3666 let t = type_at( 3661 let t = type_at(
3667 r#" 3662 r#"
3668//- /main.rs 3663//- /main.rs
@@ -3683,7 +3678,6 @@ fn test(a: i32) {
3683 3678
3684 #[test] 3679 #[test]
3685 fn match_all_arms_never() { 3680 fn match_all_arms_never() {
3686 covers!(match_all_arms_never);
3687 let t = type_at( 3681 let t = type_at(
3688 r#" 3682 r#"
3689//- /main.rs 3683//- /main.rs
@@ -3702,7 +3696,6 @@ fn test(a: i32) {
3702 3696
3703 #[test] 3697 #[test]
3704 fn match_no_never_arms() { 3698 fn match_no_never_arms() {
3705 covers!(match_no_never_arms);
3706 let t = type_at( 3699 let t = type_at(
3707 r#" 3700 r#"
3708//- /main.rs 3701//- /main.rs