aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/infer/coerce.rs14
-rw-r--r--crates/hir_ty/src/infer/expr.rs22
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
8use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 8use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
9use hir_def::lang_item::LangItemTarget; 9use hir_def::{expr::ExprId, lang_item::LangItemTarget};
10 10
11use crate::{ 11use 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
16use super::{InEnvironment, InferOk, InferResult, InferenceContext, TypeError}; 16use 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;