aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2019-08-11 23:01:15 +0100
committerKirill Bulatov <[email protected]>2019-08-26 20:44:50 +0100
commit0ce05633a170076a3624a79ed96a40c1730a8164 (patch)
treebd59c4112df517f51356b3914f48a8f9dae642c1
parentf63cfd5fca6180b51d3b00896b119def32314b71 (diff)
Fix match type inference for Never match arms
-rw-r--r--crates/ra_hir/src/ty/infer.rs36
-rw-r--r--crates/ra_hir/src/ty/tests.rs2
2 files changed, 32 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index d94e8154b..dc7101075 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 }
@@ -297,7 +296,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
297 | (Ty::Infer(InferTy::IntVar(tv)), other) 296 | (Ty::Infer(InferTy::IntVar(tv)), other)
298 | (other, Ty::Infer(InferTy::IntVar(tv))) 297 | (other, Ty::Infer(InferTy::IntVar(tv)))
299 | (Ty::Infer(InferTy::FloatVar(tv)), other) 298 | (Ty::Infer(InferTy::FloatVar(tv)), other)
300 | (other, Ty::Infer(InferTy::FloatVar(tv))) => { 299 | (other, Ty::Infer(InferTy::FloatVar(tv)))
300 if !Self::is_never(other) =>
301 {
301 // the type var is unknown since we tried to resolve it 302 // the type var is unknown since we tried to resolve it
302 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); 303 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
303 true 304 true
@@ -1080,6 +1081,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1080 }; 1081 };
1081 let input_ty = self.infer_expr(*expr, &Expectation::none()); 1082 let input_ty = self.infer_expr(*expr, &Expectation::none());
1082 1083
1084 let mut resulting_match_ty = None;
1085 let mut all_arms_never = !arms.is_empty();
1086
1083 for arm in arms { 1087 for arm in arms {
1084 for &pat in &arm.pats { 1088 for &pat in &arm.pats {
1085 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default()); 1089 let _pat_ty = self.infer_pat(pat, &input_ty, BindingMode::default());
@@ -1090,10 +1094,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1090 &Expectation::has_type(Ty::simple(TypeCtor::Bool)), 1094 &Expectation::has_type(Ty::simple(TypeCtor::Bool)),
1091 ); 1095 );
1092 } 1096 }
1093 self.infer_expr(arm.expr, &expected); 1097 let arm_ty = self.infer_expr(arm.expr, &expected);
1098 if all_arms_never && Self::is_never(&arm_ty) {
1099 resulting_match_ty = Some(arm_ty);
1100 } else {
1101 all_arms_never = false;
1102 resulting_match_ty = None;
1103 }
1094 } 1104 }
1095 1105
1096 expected.ty 1106 if let (Ty::Infer(expected_tv), Some(match_ty)) =
1107 (&expected.ty, &resulting_match_ty)
1108 {
1109 self.var_unification_table
1110 .union_value(expected_tv.to_inner(), TypeVarValue::Known(match_ty.clone()));
1111 match_ty.clone()
1112 } else {
1113 expected.ty
1114 }
1097 } 1115 }
1098 Expr::Path(p) => { 1116 Expr::Path(p) => {
1099 // FIXME this could be more efficient... 1117 // FIXME this could be more efficient...
@@ -1368,6 +1386,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1368 ty 1386 ty
1369 } 1387 }
1370 1388
1389 fn is_never(ty: &Ty) -> bool {
1390 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty {
1391 true
1392 } else {
1393 false
1394 }
1395 }
1396
1371 fn infer_block( 1397 fn infer_block(
1372 &mut self, 1398 &mut self,
1373 statements: &[Statement], 1399 statements: &[Statement],
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 0f53f156e..6bf56959d 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3600,7 +3600,7 @@ mod match_with_never_tests {
3600 use super::type_at; 3600 use super::type_at;
3601 3601
3602 #[test] 3602 #[test]
3603 fn match_compex_arm_ty() { 3603 fn match_complex_arm_ty() {
3604 let t = type_at( 3604 let t = type_at(
3605 r#" 3605 r#"
3606//- /main.rs 3606//- /main.rs