@@ -180,7 +180,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
180
180
// then that's equivalent to there existing a LUB.
181
181
if let Some ( mut err) = self . demand_suptype_diag ( pat. span , expected, pat_ty) {
182
182
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
+ } )
184
189
. is_some ( ) ) ;
185
190
}
186
191
@@ -624,14 +629,15 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
624
629
let tcx = self . tcx ;
625
630
626
631
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 {
628
633
IfDesugar { contains_else_clause } => ( true , !contains_else_clause, true ) ,
629
634
IfLetDesugar { contains_else_clause } => ( true , !contains_else_clause, false ) ,
635
+ WhileDesugar => ( false , false , true ) ,
630
636
_ => ( false , false , false ) ,
631
637
} ;
632
638
633
639
// Type check the descriminant and get its type.
634
- let discrim_ty = if if_desugar {
640
+ let discrim_ty = if force_scrutinee_bool {
635
641
// Here we want to ensure:
636
642
//
637
643
// 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");
651
657
return tcx. types . never ;
652
658
}
653
659
654
- self . warn_arms_when_scrutinee_diverges ( arms, source_if ) ;
660
+ self . warn_arms_when_scrutinee_diverges ( arms, match_src ) ;
655
661
656
662
// Otherwise, we have to union together the types that the
657
663
// arms produce and so forth.
@@ -726,7 +732,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
726
732
if source_if {
727
733
let then_expr = & arms[ 0 ] . body ;
728
734
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) ,
730
736
( _, true ) => self . if_fallback_coercion ( span, then_expr, & mut coercion) ,
731
737
( _, _) => {
732
738
let then_ty = prior_arm_ty. unwrap ( ) ;
@@ -771,9 +777,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
771
777
772
778
/// When the previously checked expression (the scrutinee) diverges,
773
779
/// 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 ) {
775
781
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
+ } ;
777
788
for arm in arms {
778
789
self . warn_if_unreachable ( arm. body . hir_id , arm. body . span , msg) ;
779
790
}
0 commit comments