@@ -15,9 +15,10 @@ use middle::pat_util::pat_is_resolved_const;
15
15
use middle:: subst:: Substs ;
16
16
use middle:: ty:: { self , Ty , TypeFoldable , LvaluePreference } ;
17
17
use check:: { check_expr, check_expr_has_type, check_expr_with_expectation} ;
18
- use check:: { check_expr_coercable_to_type , demand, FnCtxt , Expectation } ;
18
+ use check:: { demand, FnCtxt , Expectation } ;
19
19
use check:: { check_expr_with_lvalue_pref} ;
20
20
use check:: { instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type} ;
21
+ use check:: coercion;
21
22
use lint;
22
23
use require_same_types;
23
24
use util:: nodemap:: FnvHashMap ;
@@ -492,54 +493,67 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
492
493
// of execution reach it, we will panic, so bottom is an appropriate
493
494
// type in that case)
494
495
let expected = expected. adjust_for_branches ( fcx) ;
495
- let result_ty = arms. iter ( ) . fold ( fcx. infcx ( ) . next_diverging_ty_var ( ) , |result_ty, arm| {
496
- let bty = match expected {
497
- // We don't coerce to `()` so that if the match expression is a
498
- // statement it's branches can have any consistent type. That allows
499
- // us to give better error messages (pointing to a usually better
500
- // arm for inconsistent arms or to the whole match when a `()` type
501
- // is required).
502
- Expectation :: ExpectHasType ( ety) if ety != fcx. tcx ( ) . mk_nil ( ) => {
503
- check_expr_coercable_to_type ( fcx, & arm. body , ety) ;
504
- ety
505
- }
506
- _ => {
507
- check_expr_with_expectation ( fcx, & arm. body , expected) ;
508
- fcx. node_ty ( arm. body . id )
496
+ let mut result_ty = fcx. infcx ( ) . next_diverging_ty_var ( ) ;
497
+ let coerce_first = match expected {
498
+ // We don't coerce to `()` so that if the match expression is a
499
+ // statement it's branches can have any consistent type. That allows
500
+ // us to give better error messages (pointing to a usually better
501
+ // arm for inconsistent arms or to the whole match when a `()` type
502
+ // is required).
503
+ Expectation :: ExpectHasType ( ety) if ety != fcx. tcx ( ) . mk_nil ( ) => {
504
+ ety
505
+ }
506
+ _ => result_ty
507
+ } ;
508
+ for ( i, arm) in arms. iter ( ) . enumerate ( ) {
509
+ if let Some ( ref e) = arm. guard {
510
+ check_expr_has_type ( fcx, e, tcx. types . bool ) ;
511
+ }
512
+ check_expr_with_expectation ( fcx, & arm. body , expected) ;
513
+ let arm_ty = fcx. expr_ty ( & arm. body ) ;
514
+
515
+ if result_ty. references_error ( ) || arm_ty. references_error ( ) {
516
+ result_ty = tcx. types . err ;
517
+ continue ;
518
+ }
519
+
520
+ // Handle the fallback arm of a desugared if-let like a missing else.
521
+ let is_if_let_fallback = match match_src {
522
+ hir:: MatchSource :: IfLetDesugar { contains_else_clause : false } => {
523
+ i == arms. len ( ) - 1 && arm_ty. is_nil ( )
509
524
}
525
+ _ => false
510
526
} ;
511
527
512
- if let Some ( ref e) = arm. guard {
513
- check_expr_has_type ( fcx, & e, tcx. types . bool ) ;
514
- }
528
+ let origin = if is_if_let_fallback {
529
+ TypeOrigin :: IfExpressionWithNoElse ( expr. span )
530
+ } else {
531
+ TypeOrigin :: MatchExpressionArm ( expr. span , arm. body . span , match_src)
532
+ } ;
515
533
516
- if result_ty. references_error ( ) || bty. references_error ( ) {
517
- tcx. types . err
534
+ let result = if is_if_let_fallback {
535
+ fcx. infcx ( ) . eq_types ( true , origin, arm_ty, result_ty) . map ( |_| arm_ty)
536
+ } else if i == 0 {
537
+ // Special-case the first arm, as it has no "previous expressions".
538
+ coercion:: try ( fcx, & arm. body , coerce_first)
518
539
} else {
519
- let ( origin, expected, found) = match match_src {
520
- /* if-let construct without an else block */
521
- hir:: MatchSource :: IfLetDesugar { contains_else_clause }
522
- if !contains_else_clause => (
523
- TypeOrigin :: IfExpressionWithNoElse ( expr. span ) ,
524
- bty,
525
- result_ty,
526
- ) ,
527
- _ => (
528
- TypeOrigin :: MatchExpressionArm ( expr. span , arm. body . span , match_src) ,
529
- result_ty,
530
- bty,
531
- ) ,
532
- } ;
540
+ let prev_arms = || arms[ ..i] . iter ( ) . map ( |arm| & * arm. body ) ;
541
+ coercion:: try_find_lub ( fcx, origin, prev_arms, result_ty, & arm. body )
542
+ } ;
533
543
534
- infer:: common_supertype (
535
- fcx. infcx ( ) ,
536
- origin,
537
- true ,
538
- expected,
539
- found,
540
- )
541
- }
542
- } ) ;
544
+ result_ty = match result {
545
+ Ok ( ty) => ty,
546
+ Err ( e) => {
547
+ let ( expected, found) = if is_if_let_fallback {
548
+ ( arm_ty, result_ty)
549
+ } else {
550
+ ( result_ty, arm_ty)
551
+ } ;
552
+ fcx. infcx ( ) . report_mismatched_types ( origin, expected, found, e) ;
553
+ fcx. tcx ( ) . types . err
554
+ }
555
+ } ;
556
+ }
543
557
544
558
fcx. write_ty ( expr. id , result_ty) ;
545
559
}
0 commit comments