@@ -180,7 +180,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
180180 // then that's equivalent to there existing a LUB.
181181 if let Some ( mut err) = self . demand_suptype_diag ( pat. span , expected, pat_ty) {
182182 err. emit_unless ( discrim_span
183- . filter ( |& s| s. is_compiler_desugaring ( CompilerDesugaringKind :: IfTemporary ) )
183+ . filter ( |& s| {
184+ // In the case of `if`- and `while`-expressions we've already checked
185+ // that `scrutinee: bool`. We know that the pattern is `true`,
186+ // so an error here would be a duplicate and from the wrong POV.
187+ s. is_compiler_desugaring ( CompilerDesugaringKind :: CondTemporary )
188+ } )
184189 . is_some ( ) ) ;
185190 }
186191
@@ -624,14 +629,15 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
624629 let tcx = self . tcx ;
625630
626631 use hir:: MatchSource :: * ;
627- let ( source_if, if_no_else, if_desugar ) = match match_src {
632+ let ( source_if, if_no_else, force_scrutinee_bool ) = match match_src {
628633 IfDesugar { contains_else_clause } => ( true , !contains_else_clause, true ) ,
629634 IfLetDesugar { contains_else_clause } => ( true , !contains_else_clause, false ) ,
635+ WhileDesugar => ( false , false , true ) ,
630636 _ => ( false , false , false ) ,
631637 } ;
632638
633639 // Type check the descriminant and get its type.
634- let discrim_ty = if if_desugar {
640+ let discrim_ty = if force_scrutinee_bool {
635641 // Here we want to ensure:
636642 //
637643 // 1. That default match bindings are *not* accepted in the condition of an
@@ -651,7 +657,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
651657 return tcx. types . never ;
652658 }
653659
654- self . warn_arms_when_scrutinee_diverges ( arms, source_if ) ;
660+ self . warn_arms_when_scrutinee_diverges ( arms, match_src ) ;
655661
656662 // Otherwise, we have to union together the types that the
657663 // arms produce and so forth.
@@ -726,7 +732,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
726732 if source_if {
727733 let then_expr = & arms[ 0 ] . body ;
728734 match ( i, if_no_else) {
729- ( 0 , _) => coercion. coerce ( self , & self . misc ( span) , then_expr , arm_ty) ,
735+ ( 0 , _) => coercion. coerce ( self , & self . misc ( span) , & arm . body , arm_ty) ,
730736 ( _, true ) => self . if_fallback_coercion ( span, then_expr, & mut coercion) ,
731737 ( _, _) => {
732738 let then_ty = prior_arm_ty. unwrap ( ) ;
@@ -771,9 +777,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
771777
772778 /// When the previously checked expression (the scrutinee) diverges,
773779 /// warn the user about the match arms being unreachable.
774- fn warn_arms_when_scrutinee_diverges ( & self , arms : & ' tcx [ hir:: Arm ] , source_if : bool ) {
780+ fn warn_arms_when_scrutinee_diverges ( & self , arms : & ' tcx [ hir:: Arm ] , source : hir :: MatchSource ) {
775781 if self . diverges . get ( ) . always ( ) {
776- let msg = if source_if { "block in `if` expression" } else { "arm" } ;
782+ use hir:: MatchSource :: * ;
783+ let msg = match source {
784+ IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression" ,
785+ WhileDesugar { .. } | WhileLetDesugar { .. } => "block in `while` expression" ,
786+ _ => "arm" ,
787+ } ;
777788 for arm in arms {
778789 self . warn_if_unreachable ( arm. body . hir_id , arm. body . span , msg) ;
779790 }
0 commit comments