Skip to content

Commit 046cd90

Browse files
committed
typeck/expr.rs: extract out check_expr_loop.
1 parent 867ff1b commit 046cd90

File tree

1 file changed

+48
-38
lines changed

1 file changed

+48
-38
lines changed

src/librustc_typeck/check/expr.rs

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)