From 6e5637983c155b2914647bb5e437337a44a63a7d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 21 May 2021 17:48:15 +0200 Subject: Record type mismatches for failed coercions in match etc. --- crates/hir_ty/src/infer/coerce.rs | 14 +++++++++----- 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 @@ //! librustc_typeck/check/coercion.rs. use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; -use hir_def::lang_item::LangItemTarget; +use hir_def::{expr::ExprId, lang_item::LangItemTarget}; use crate::{ - autoderef, static_lifetime, Canonical, DomainGoal, FnPointer, FnSig, Interner, Solution, - Substitution, Ty, TyBuilder, TyExt, TyKind, + autoderef, infer::TypeMismatch, static_lifetime, Canonical, DomainGoal, FnPointer, FnSig, + Interner, Solution, Substitution, Ty, TyBuilder, TyExt, TyKind, }; use super::{InEnvironment, InferOk, InferResult, InferenceContext, TypeError}; @@ -40,7 +40,7 @@ impl<'a> InferenceContext<'a> { /// coerce both to function pointers; /// - if we were concerned with lifetime subtyping, we'd need to look for a /// least upper bound. - pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { + pub(super) fn coerce_merge_branch(&mut self, id: Option, ty1: &Ty, ty2: &Ty) -> Ty { let ty1 = self.resolve_ty_shallow(ty1); let ty2 = self.resolve_ty_shallow(ty2); // Special case: two function types. Try to coerce both to @@ -80,7 +80,11 @@ impl<'a> InferenceContext<'a> { } else if self.coerce(&ty1, &ty2) { ty2.clone() } else { - // TODO record a type mismatch + if let Some(id) = id { + self.result + .type_mismatches + .insert(id.into(), TypeMismatch { expected: ty1.clone(), actual: ty2.clone() }); + } cov_mark::hit!(coerce_merge_fail_fallback); ty1.clone() } 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> { let mut result_ty = self.table.new_type_var(); let then_ty = self.infer_expr_inner(*then_branch, &expected); both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); - result_ty = self.coerce_merge_branch(&result_ty, &then_ty); + result_ty = self.coerce_merge_branch(Some(*then_branch), &result_ty, &then_ty); let else_ty = match else_branch { Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), None => TyBuilder::unit(), }; both_arms_diverge &= self.diverges; - result_ty = self.coerce_merge_branch(&result_ty, &else_ty); + // FIXME: create a synthetic `else {}` so we have something to refer to here instead of None? + result_ty = self.coerce_merge_branch(*else_branch, &result_ty, &else_ty); self.diverges = condition_diverges | both_arms_diverge; @@ -358,7 +359,7 @@ impl<'a> InferenceContext<'a> { let arm_ty = self.infer_expr_inner(arm.expr, &expected); all_arms_diverge &= self.diverges; - result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); + result_ty = self.coerce_merge_branch(Some(arm.expr), &result_ty, &arm_ty); } self.diverges = matchee_diverges | all_arms_diverge; @@ -372,12 +373,6 @@ impl<'a> InferenceContext<'a> { } Expr::Continue { .. } => TyKind::Never.intern(&Interner), Expr::Break { expr, label } => { - let val_ty = if let Some(expr) = expr { - self.infer_expr(*expr, &Expectation::none()) - } else { - TyBuilder::unit() - }; - let last_ty = if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { ctxt.break_ty.clone() @@ -385,7 +380,14 @@ impl<'a> InferenceContext<'a> { self.err_ty() }; - let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); + let val_ty = if let Some(expr) = expr { + self.infer_expr(*expr, &Expectation::none()) + } else { + TyBuilder::unit() + }; + + // FIXME: create a synthetic `()` during lowering so we have something to refer to here? + let merged_type = self.coerce_merge_branch(*expr, &last_ty, &val_ty); if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { ctxt.break_ty = merged_type; -- cgit v1.2.3