diff options
author | Kirill Bulatov <[email protected]> | 2019-08-11 23:01:15 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2019-08-26 20:44:50 +0100 |
commit | 0ce05633a170076a3624a79ed96a40c1730a8164 (patch) | |
tree | bd59c4112df517f51356b3914f48a8f9dae642c1 /crates/ra_hir/src/ty | |
parent | f63cfd5fca6180b51d3b00896b119def32314b71 (diff) |
Fix match type inference for Never match arms
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 2 |
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 |