Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/expr.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/expr.rs | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 96218e4fb0..353bf6568c 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -26,7 +26,10 @@ use crate::{ autoderef::{builtin_deref, deref_by_trait, Autoderef}, consteval, infer::{ - coerce::CoerceMany, find_continuable, pat::contains_explicit_ref_binding, BreakableKind, + coerce::{CoerceMany, CoercionCause}, + find_continuable, + pat::contains_explicit_ref_binding, + BreakableKind, }, lang_items::lang_items_for_bin_op, lower::{ @@ -132,24 +135,28 @@ impl<'a> InferenceContext<'a> { ); let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); - let mut both_arms_diverge = Diverges::Always; let then_ty = self.infer_expr_inner(then_branch, expected); - both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); + let then_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table)); - coerce.coerce(self, Some(then_branch), &then_ty); + coerce.coerce(self, Some(then_branch), &then_ty, CoercionCause::Expr(then_branch)); match else_branch { Some(else_branch) => { let else_ty = self.infer_expr_inner(else_branch, expected); - coerce.coerce(self, Some(else_branch), &else_ty); + let else_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); + coerce.coerce( + self, + Some(else_branch), + &else_ty, + CoercionCause::Expr(else_branch), + ); + self.diverges = condition_diverges | then_diverges & else_diverges; } None => { - coerce.coerce_forced_unit(self); + coerce.coerce_forced_unit(self, CoercionCause::Expr(tgt_expr)); + self.diverges = condition_diverges; } } - both_arms_diverge &= self.diverges; - - self.diverges = condition_diverges | both_arms_diverge; coerce.complete(self) } @@ -444,7 +451,7 @@ impl<'a> InferenceContext<'a> { let arm_ty = self.infer_expr_inner(arm.expr, &expected); all_arms_diverge &= self.diverges; - coerce.coerce(self, Some(arm.expr), &arm_ty); + coerce.coerce(self, Some(arm.expr), &arm_ty, CoercionCause::Expr(arm.expr)); } self.diverges = matchee_diverges | all_arms_diverge; @@ -492,7 +499,11 @@ impl<'a> InferenceContext<'a> { match find_breakable(&mut self.breakables, label) { Some(ctxt) => match ctxt.coerce.take() { Some(mut coerce) => { - coerce.coerce(self, expr, &val_ty); + let cause = match expr { + Some(expr) => CoercionCause::Expr(expr), + None => CoercionCause::Expr(tgt_expr), + }; + coerce.coerce(self, expr, &val_ty, cause); // Avoiding borrowck let ctxt = find_breakable(&mut self.breakables, label) @@ -512,7 +523,7 @@ impl<'a> InferenceContext<'a> { } self.result.standard_types.never.clone() } - &Expr::Return { expr } => self.infer_expr_return(expr), + &Expr::Return { expr } => self.infer_expr_return(tgt_expr, expr), Expr::Yield { expr } => { if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() { if let Some(expr) = expr { @@ -952,7 +963,7 @@ impl<'a> InferenceContext<'a> { let mut coerce = CoerceMany::new(elem_ty); for &expr in elements.iter() { let cur_elem_ty = self.infer_expr_inner(expr, &expected); - coerce.coerce(self, Some(expr), &cur_elem_ty); + coerce.coerce(self, Some(expr), &cur_elem_ty, CoercionCause::Expr(expr)); } ( coerce.complete(self), @@ -997,18 +1008,18 @@ impl<'a> InferenceContext<'a> { .expected_ty(); let return_expr_ty = self.infer_expr_inner(expr, &Expectation::HasType(ret_ty)); let mut coerce_many = self.return_coercion.take().unwrap(); - coerce_many.coerce(self, Some(expr), &return_expr_ty); + coerce_many.coerce(self, Some(expr), &return_expr_ty, CoercionCause::Expr(expr)); self.return_coercion = Some(coerce_many); } - fn infer_expr_return(&mut self, expr: Option<ExprId>) -> Ty { + fn infer_expr_return(&mut self, ret: ExprId, expr: Option<ExprId>) -> Ty { match self.return_coercion { Some(_) => { if let Some(expr) = expr { self.infer_return(expr); } else { let mut coerce = self.return_coercion.take().unwrap(); - coerce.coerce_forced_unit(self); + coerce.coerce_forced_unit(self, CoercionCause::Expr(ret)); self.return_coercion = Some(coerce); } } |