@@ -96,44 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
96
96
self . check_expr_while ( cond, body, expr)
97
97
}
98
98
ExprKind :: Loop ( ref body, _, source) => {
99
- let coerce = match source {
100
- // you can only use break with a value from a normal `loop { }`
101
- hir:: LoopSource :: Loop => {
102
- let coerce_to = expected. coercion_target_type ( self , body. span ) ;
103
- Some ( CoerceMany :: new ( coerce_to) )
104
- }
105
-
106
- hir:: LoopSource :: WhileLet |
107
- hir:: LoopSource :: ForLoop => {
108
- None
109
- }
110
- } ;
111
-
112
- let ctxt = BreakableCtxt {
113
- coerce,
114
- may_break : false , // Will get updated if/when we find a `break`.
115
- } ;
116
-
117
- let ( ctxt, ( ) ) = self . with_breakable_ctxt ( expr. hir_id , ctxt, || {
118
- self . check_block_no_value ( & body) ;
119
- } ) ;
120
-
121
- if ctxt. may_break {
122
- // No way to know whether it's diverging because
123
- // of a `break` or an outer `break` or `return`.
124
- self . diverges . set ( Diverges :: Maybe ) ;
125
- }
126
-
127
- // If we permit break with a value, then result type is
128
- // the LUB of the breaks (possibly ! if none); else, it
129
- // is nil. This makes sense because infinite loops
130
- // (which would have type !) are only possible iff we
131
- // permit break with a value [1].
132
- if ctxt. coerce . is_none ( ) && !ctxt. may_break {
133
- // [1]
134
- self . tcx . sess . delay_span_bug ( body. span , "no coercion, but loop may not break" ) ;
135
- }
136
- ctxt. coerce . map ( |c| c. complete ( self ) ) . unwrap_or_else ( || self . tcx . mk_unit ( ) )
99
+ self . check_expr_loop ( body, source, expected, expr)
137
100
}
138
101
ExprKind :: Match ( ref discrim, ref arms, match_src) => {
139
102
self . check_match ( expr, & discrim, arms, expected, match_src)
@@ -796,4 +759,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796
759
797
760
self . tcx . mk_unit ( )
798
761
}
762
+
763
+ fn check_expr_loop (
764
+ & self ,
765
+ body : & ' tcx hir:: Block ,
766
+ source : hir:: LoopSource ,
767
+ expected : Expectation < ' tcx > ,
768
+ expr : & ' tcx hir:: Expr ,
769
+ ) -> Ty < ' tcx > {
770
+ let coerce = match source {
771
+ // you can only use break with a value from a normal `loop { }`
772
+ hir:: LoopSource :: Loop => {
773
+ let coerce_to = expected. coercion_target_type ( self , body. span ) ;
774
+ Some ( CoerceMany :: new ( coerce_to) )
775
+ }
776
+
777
+ hir:: LoopSource :: WhileLet |
778
+ hir:: LoopSource :: ForLoop => {
779
+ None
780
+ }
781
+ } ;
782
+
783
+ let ctxt = BreakableCtxt {
784
+ coerce,
785
+ may_break : false , // Will get updated if/when we find a `break`.
786
+ } ;
787
+
788
+ let ( ctxt, ( ) ) = self . with_breakable_ctxt ( expr. hir_id , ctxt, || {
789
+ self . check_block_no_value ( & body) ;
790
+ } ) ;
791
+
792
+ if ctxt. may_break {
793
+ // No way to know whether it's diverging because
794
+ // of a `break` or an outer `break` or `return`.
795
+ self . diverges . set ( Diverges :: Maybe ) ;
796
+ }
797
+
798
+ // If we permit break with a value, then result type is
799
+ // the LUB of the breaks (possibly ! if none); else, it
800
+ // is nil. This makes sense because infinite loops
801
+ // (which would have type !) are only possible iff we
802
+ // permit break with a value [1].
803
+ if ctxt. coerce . is_none ( ) && !ctxt. may_break {
804
+ // [1]
805
+ self . tcx . sess . delay_span_bug ( body. span , "no coercion, but loop may not break" ) ;
806
+ }
807
+ ctxt. coerce . map ( |c| c. complete ( self ) ) . unwrap_or_else ( || self . tcx . mk_unit ( ) )
808
+ }
799
809
}
0 commit comments