@@ -26,7 +26,10 @@ use crate::{
26
26
autoderef:: { builtin_deref, deref_by_trait, Autoderef } ,
27
27
consteval,
28
28
infer:: {
29
- coerce:: CoerceMany , find_continuable, pat:: contains_explicit_ref_binding, BreakableKind ,
29
+ coerce:: { CoerceMany , CoercionCause } ,
30
+ find_continuable,
31
+ pat:: contains_explicit_ref_binding,
32
+ BreakableKind ,
30
33
} ,
31
34
lang_items:: lang_items_for_bin_op,
32
35
lower:: {
@@ -132,24 +135,28 @@ impl<'a> InferenceContext<'a> {
132
135
) ;
133
136
134
137
let condition_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
135
- let mut both_arms_diverge = Diverges :: Always ;
136
138
137
139
let then_ty = self . infer_expr_inner ( then_branch, expected) ;
138
- both_arms_diverge & = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
140
+ let then_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
139
141
let mut coerce = CoerceMany :: new ( expected. coercion_target_type ( & mut self . table ) ) ;
140
- coerce. coerce ( self , Some ( then_branch) , & then_ty) ;
142
+ coerce. coerce ( self , Some ( then_branch) , & then_ty, CoercionCause :: Expr ( then_branch ) ) ;
141
143
match else_branch {
142
144
Some ( else_branch) => {
143
145
let else_ty = self . infer_expr_inner ( else_branch, expected) ;
144
- coerce. coerce ( self , Some ( else_branch) , & else_ty) ;
146
+ let else_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
147
+ coerce. coerce (
148
+ self ,
149
+ Some ( else_branch) ,
150
+ & else_ty,
151
+ CoercionCause :: Expr ( else_branch) ,
152
+ ) ;
153
+ self . diverges = condition_diverges | then_diverges & else_diverges;
145
154
}
146
155
None => {
147
- coerce. coerce_forced_unit ( self ) ;
156
+ coerce. coerce_forced_unit ( self , CoercionCause :: Expr ( tgt_expr) ) ;
157
+ self . diverges = condition_diverges;
148
158
}
149
159
}
150
- both_arms_diverge &= self . diverges ;
151
-
152
- self . diverges = condition_diverges | both_arms_diverge;
153
160
154
161
coerce. complete ( self )
155
162
}
@@ -444,7 +451,7 @@ impl<'a> InferenceContext<'a> {
444
451
445
452
let arm_ty = self . infer_expr_inner ( arm. expr , & expected) ;
446
453
all_arms_diverge &= self . diverges ;
447
- coerce. coerce ( self , Some ( arm. expr ) , & arm_ty) ;
454
+ coerce. coerce ( self , Some ( arm. expr ) , & arm_ty, CoercionCause :: Expr ( arm . expr ) ) ;
448
455
}
449
456
450
457
self . diverges = matchee_diverges | all_arms_diverge;
@@ -492,7 +499,11 @@ impl<'a> InferenceContext<'a> {
492
499
match find_breakable ( & mut self . breakables , label) {
493
500
Some ( ctxt) => match ctxt. coerce . take ( ) {
494
501
Some ( mut coerce) => {
495
- coerce. coerce ( self , expr, & val_ty) ;
502
+ let cause = match expr {
503
+ Some ( expr) => CoercionCause :: Expr ( expr) ,
504
+ None => CoercionCause :: Expr ( tgt_expr) ,
505
+ } ;
506
+ coerce. coerce ( self , expr, & val_ty, cause) ;
496
507
497
508
// Avoiding borrowck
498
509
let ctxt = find_breakable ( & mut self . breakables , label)
@@ -512,7 +523,7 @@ impl<'a> InferenceContext<'a> {
512
523
}
513
524
self . result . standard_types . never . clone ( )
514
525
}
515
- & Expr :: Return { expr } => self . infer_expr_return ( expr) ,
526
+ & Expr :: Return { expr } => self . infer_expr_return ( tgt_expr , expr) ,
516
527
Expr :: Yield { expr } => {
517
528
if let Some ( ( resume_ty, yield_ty) ) = self . resume_yield_tys . clone ( ) {
518
529
if let Some ( expr) = expr {
@@ -952,7 +963,7 @@ impl<'a> InferenceContext<'a> {
952
963
let mut coerce = CoerceMany :: new ( elem_ty) ;
953
964
for & expr in elements. iter ( ) {
954
965
let cur_elem_ty = self . infer_expr_inner ( expr, & expected) ;
955
- coerce. coerce ( self , Some ( expr) , & cur_elem_ty) ;
966
+ coerce. coerce ( self , Some ( expr) , & cur_elem_ty, CoercionCause :: Expr ( expr ) ) ;
956
967
}
957
968
(
958
969
coerce. complete ( self ) ,
@@ -997,18 +1008,18 @@ impl<'a> InferenceContext<'a> {
997
1008
. expected_ty ( ) ;
998
1009
let return_expr_ty = self . infer_expr_inner ( expr, & Expectation :: HasType ( ret_ty) ) ;
999
1010
let mut coerce_many = self . return_coercion . take ( ) . unwrap ( ) ;
1000
- coerce_many. coerce ( self , Some ( expr) , & return_expr_ty) ;
1011
+ coerce_many. coerce ( self , Some ( expr) , & return_expr_ty, CoercionCause :: Expr ( expr ) ) ;
1001
1012
self . return_coercion = Some ( coerce_many) ;
1002
1013
}
1003
1014
1004
- fn infer_expr_return ( & mut self , expr : Option < ExprId > ) -> Ty {
1015
+ fn infer_expr_return ( & mut self , ret : ExprId , expr : Option < ExprId > ) -> Ty {
1005
1016
match self . return_coercion {
1006
1017
Some ( _) => {
1007
1018
if let Some ( expr) = expr {
1008
1019
self . infer_return ( expr) ;
1009
1020
} else {
1010
1021
let mut coerce = self . return_coercion . take ( ) . unwrap ( ) ;
1011
- coerce. coerce_forced_unit ( self ) ;
1022
+ coerce. coerce_forced_unit ( self , CoercionCause :: Expr ( ret ) ) ;
1012
1023
self . return_coercion = Some ( coerce) ;
1013
1024
}
1014
1025
}
0 commit comments