Record type mismatches for failed coercions in match etc.
This commit is contained in:
parent
556c9cebdb
commit
6e5637983c
@ -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<ExprId>, 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()
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user