@@ -96,44 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9696 self . check_expr_while ( cond, body, expr)
9797 }
9898 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)
137100 }
138101 ExprKind :: Match ( ref discrim, ref arms, match_src) => {
139102 self . check_match ( expr, & discrim, arms, expected, match_src)
@@ -796,4 +759,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796759
797760 self . tcx . mk_unit ( )
798761 }
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+ }
799809}
0 commit comments