diff options
author | Florian Diebold <[email protected]> | 2021-05-21 16:48:15 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-05-21 17:23:03 +0100 |
commit | 6e5637983c155b2914647bb5e437337a44a63a7d (patch) | |
tree | 7329b76bdc2424075fafcac3108d70f1d8bae82c /crates/hir_ty | |
parent | 556c9cebdb91278702263df4ac8c99ec24ab331a (diff) |
Record type mismatches for failed coercions in match etc.
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 14 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 22 |
2 files changed, 21 insertions, 15 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 03dd6ae76..40b4db926 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -6,11 +6,11 @@ | |||
6 | //! librustc_typeck/check/coercion.rs. | 6 | //! librustc_typeck/check/coercion.rs. |
7 | 7 | ||
8 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 8 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
9 | use hir_def::lang_item::LangItemTarget; | 9 | use hir_def::{expr::ExprId, lang_item::LangItemTarget}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | autoderef, static_lifetime, Canonical, DomainGoal, FnPointer, FnSig, Interner, Solution, | 12 | autoderef, infer::TypeMismatch, static_lifetime, Canonical, DomainGoal, FnPointer, FnSig, |
13 | Substitution, Ty, TyBuilder, TyExt, TyKind, | 13 | Interner, Solution, Substitution, Ty, TyBuilder, TyExt, TyKind, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use super::{InEnvironment, InferOk, InferResult, InferenceContext, TypeError}; | 16 | use super::{InEnvironment, InferOk, InferResult, InferenceContext, TypeError}; |
@@ -40,7 +40,7 @@ impl<'a> InferenceContext<'a> { | |||
40 | /// coerce both to function pointers; | 40 | /// coerce both to function pointers; |
41 | /// - if we were concerned with lifetime subtyping, we'd need to look for a | 41 | /// - if we were concerned with lifetime subtyping, we'd need to look for a |
42 | /// least upper bound. | 42 | /// least upper bound. |
43 | pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { | 43 | pub(super) fn coerce_merge_branch(&mut self, id: Option<ExprId>, ty1: &Ty, ty2: &Ty) -> Ty { |
44 | let ty1 = self.resolve_ty_shallow(ty1); | 44 | let ty1 = self.resolve_ty_shallow(ty1); |
45 | let ty2 = self.resolve_ty_shallow(ty2); | 45 | let ty2 = self.resolve_ty_shallow(ty2); |
46 | // Special case: two function types. Try to coerce both to | 46 | // Special case: two function types. Try to coerce both to |
@@ -80,7 +80,11 @@ impl<'a> InferenceContext<'a> { | |||
80 | } else if self.coerce(&ty1, &ty2) { | 80 | } else if self.coerce(&ty1, &ty2) { |
81 | ty2.clone() | 81 | ty2.clone() |
82 | } else { | 82 | } else { |
83 | // TODO record a type mismatch | 83 | if let Some(id) = id { |
84 | self.result | ||
85 | .type_mismatches | ||
86 | .insert(id.into(), TypeMismatch { expected: ty1.clone(), actual: ty2.clone() }); | ||
87 | } | ||
84 | cov_mark::hit!(coerce_merge_fail_fallback); | 88 | cov_mark::hit!(coerce_merge_fail_fallback); |
85 | ty1.clone() | 89 | ty1.clone() |
86 | } | 90 | } |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 4ef847d3a..08c05c67c 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -138,13 +138,14 @@ impl<'a> InferenceContext<'a> { | |||
138 | let mut result_ty = self.table.new_type_var(); | 138 | let mut result_ty = self.table.new_type_var(); |
139 | let then_ty = self.infer_expr_inner(*then_branch, &expected); | 139 | let then_ty = self.infer_expr_inner(*then_branch, &expected); |
140 | both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); | 140 | both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); |
141 | result_ty = self.coerce_merge_branch(&result_ty, &then_ty); | 141 | result_ty = self.coerce_merge_branch(Some(*then_branch), &result_ty, &then_ty); |
142 | let else_ty = match else_branch { | 142 | let else_ty = match else_branch { |
143 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), | 143 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
144 | None => TyBuilder::unit(), | 144 | None => TyBuilder::unit(), |
145 | }; | 145 | }; |
146 | both_arms_diverge &= self.diverges; | 146 | both_arms_diverge &= self.diverges; |
147 | result_ty = self.coerce_merge_branch(&result_ty, &else_ty); | 147 | // FIXME: create a synthetic `else {}` so we have something to refer to here instead of None? |
148 | result_ty = self.coerce_merge_branch(*else_branch, &result_ty, &else_ty); | ||
148 | 149 | ||
149 | self.diverges = condition_diverges | both_arms_diverge; | 150 | self.diverges = condition_diverges | both_arms_diverge; |
150 | 151 | ||
@@ -358,7 +359,7 @@ impl<'a> InferenceContext<'a> { | |||
358 | 359 | ||
359 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); | 360 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); |
360 | all_arms_diverge &= self.diverges; | 361 | all_arms_diverge &= self.diverges; |
361 | result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); | 362 | result_ty = self.coerce_merge_branch(Some(arm.expr), &result_ty, &arm_ty); |
362 | } | 363 | } |
363 | 364 | ||
364 | self.diverges = matchee_diverges | all_arms_diverge; | 365 | self.diverges = matchee_diverges | all_arms_diverge; |
@@ -372,12 +373,6 @@ impl<'a> InferenceContext<'a> { | |||
372 | } | 373 | } |
373 | Expr::Continue { .. } => TyKind::Never.intern(&Interner), | 374 | Expr::Continue { .. } => TyKind::Never.intern(&Interner), |
374 | Expr::Break { expr, label } => { | 375 | Expr::Break { expr, label } => { |
375 | let val_ty = if let Some(expr) = expr { | ||
376 | self.infer_expr(*expr, &Expectation::none()) | ||
377 | } else { | ||
378 | TyBuilder::unit() | ||
379 | }; | ||
380 | |||
381 | let last_ty = | 376 | let last_ty = |
382 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { | 377 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
383 | ctxt.break_ty.clone() | 378 | ctxt.break_ty.clone() |
@@ -385,7 +380,14 @@ impl<'a> InferenceContext<'a> { | |||
385 | self.err_ty() | 380 | self.err_ty() |
386 | }; | 381 | }; |
387 | 382 | ||
388 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | 383 | let val_ty = if let Some(expr) = expr { |
384 | self.infer_expr(*expr, &Expectation::none()) | ||
385 | } else { | ||
386 | TyBuilder::unit() | ||
387 | }; | ||
388 | |||
389 | // FIXME: create a synthetic `()` during lowering so we have something to refer to here? | ||
390 | let merged_type = self.coerce_merge_branch(*expr, &last_ty, &val_ty); | ||
389 | 391 | ||
390 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { | 392 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
391 | ctxt.break_ty = merged_type; | 393 | ctxt.break_ty = merged_type; |