@@ -77,6 +77,7 @@ type parameter).
77
77
*/
78
78
79
79
pub use self :: Expectation :: * ;
80
+ use self :: coercion:: CoerceMany ;
80
81
pub use self :: compare_method:: { compare_impl_method, compare_const_impl} ;
81
82
use self :: TupleArgumentsFlag :: * ;
82
83
@@ -299,12 +300,23 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
299
300
}
300
301
}
301
302
303
+ /// It sometimes happens that we want to turn an expectation into
304
+ /// a **hard constraint** (i.e., something that must be satisfied
305
+ /// for the program to type-check). `only_has_type` will return
306
+ /// such a constraint, if it exists.
302
307
fn only_has_type ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > ) -> Option < Ty < ' tcx > > {
303
308
match self . resolve ( fcx) {
304
309
ExpectHasType ( ty) => Some ( ty) ,
305
310
_ => None
306
311
}
307
312
}
313
+
314
+ /// Like `only_has_type`, but instead of returning `None` if no
315
+ /// hard constraint exists, creates a fresh type variable.
316
+ fn only_has_type_or_fresh_var ( self , fcx : & FnCtxt < ' a , ' gcx , ' tcx > , span : Span ) -> Ty < ' tcx > {
317
+ self . only_has_type ( fcx)
318
+ . unwrap_or_else ( || fcx. next_ty_var ( TypeVariableOrigin :: MiscVariable ( span) ) )
319
+ }
308
320
}
309
321
310
322
#[ derive( Copy , Clone ) ]
@@ -2743,54 +2755,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2743
2755
let then_diverges = self . diverges . get ( ) ;
2744
2756
self . diverges . set ( Diverges :: Maybe ) ;
2745
2757
2746
- let unit = self . tcx . mk_nil ( ) ;
2747
- let ( cause, expected_ty, found_ty, result) ;
2758
+ // We've already taken the expected type's preferences
2759
+ // into account when typing the `then` branch. To figure
2760
+ // out the initial shot at a LUB, we thus only consider
2761
+ // `expected` if it represents a *hard* constraint
2762
+ // (`only_has_type`); otherwise, we just go with a
2763
+ // fresh type variable.
2764
+ let coerce_to_ty = expected. only_has_type_or_fresh_var ( self , sp) ;
2765
+ let mut coerce = CoerceMany :: new ( coerce_to_ty) ;
2766
+
2767
+ let if_cause = self . cause ( sp, ObligationCauseCode :: IfExpression ) ;
2768
+ coerce. coerce ( self , & if_cause, then_expr, then_ty) ;
2769
+
2748
2770
if let Some ( else_expr) = opt_else_expr {
2749
2771
let else_ty = self . check_expr_with_expectation ( else_expr, expected) ;
2750
2772
let else_diverges = self . diverges . get ( ) ;
2751
- cause = self . cause ( sp, ObligationCauseCode :: IfExpression ) ;
2752
-
2753
- // Only try to coerce-unify if we have a then expression
2754
- // to assign coercions to, otherwise it's () or diverging.
2755
- expected_ty = then_ty;
2756
- found_ty = else_ty;
2757
-
2758
- let coerce_to = expected. only_has_type ( self ) . unwrap_or ( then_ty) ;
2759
- result = {
2760
- self . try_coerce ( then_expr, then_ty, coerce_to)
2761
- . and_then ( |t| {
2762
- self . try_find_coercion_lub ( & cause, || Some ( then_expr) , t, else_expr, else_ty)
2763
- } )
2764
- } ;
2773
+
2774
+ coerce. coerce ( self , & if_cause, else_expr, else_ty) ;
2765
2775
2766
2776
// We won't diverge unless both branches do (or the condition does).
2767
2777
self . diverges . set ( cond_diverges | then_diverges & else_diverges) ;
2768
2778
} else {
2779
+ let else_cause = self . cause ( sp, ObligationCauseCode :: IfExpressionWithNoElse ) ;
2780
+ coerce. coerce_forced_unit ( self , & else_cause) ;
2781
+
2769
2782
// If the condition is false we can't diverge.
2770
2783
self . diverges . set ( cond_diverges) ;
2771
-
2772
- cause = self . cause ( sp, ObligationCauseCode :: IfExpressionWithNoElse ) ;
2773
- expected_ty = unit;
2774
- found_ty = then_ty;
2775
- result = self . eq_types ( true , & cause, unit, then_ty)
2776
- . map ( |ok| {
2777
- self . register_infer_ok_obligations ( ok) ;
2778
- unit
2779
- } ) ;
2780
2784
}
2781
2785
2782
- match result {
2783
- Ok ( ty) => {
2784
- if cond_ty. references_error ( ) {
2785
- self . tcx . types . err
2786
- } else {
2787
- ty
2788
- }
2789
- }
2790
- Err ( e) => {
2791
- self . report_mismatched_types ( & cause, expected_ty, found_ty, e) . emit ( ) ;
2792
- self . tcx . types . err
2793
- }
2786
+ let result_ty = coerce. complete ( self ) ;
2787
+ if cond_ty. references_error ( ) {
2788
+ self . tcx . types . err
2789
+ } else {
2790
+ result_ty
2794
2791
}
2795
2792
}
2796
2793
0 commit comments