Properly implement labeled breaks in while conditions
This commit is contained in:
parent
5205e2f8b8
commit
4d65622dcd
12 changed files with 247 additions and 58 deletions
|
|
@ -241,6 +241,22 @@ match 5u32 {
|
|||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0583: r##"
|
||||
`break` or `continue` must include a label when used in the condition of a
|
||||
`while` loop.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
```compile_fail
|
||||
while break {}
|
||||
```
|
||||
|
||||
To fix this, add a label specifying which loop is being broken out of:
|
||||
```
|
||||
`foo: while break `foo {}
|
||||
```
|
||||
"##
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
|
|
|
|||
|
|
@ -87,11 +87,21 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||
self.with_context(Closure, |v| v.visit_nested_body(b));
|
||||
}
|
||||
hir::ExprBreak(label, ref opt_expr) => {
|
||||
let loop_id = match label.loop_id.into() {
|
||||
Ok(loop_id) => loop_id,
|
||||
Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
|
||||
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
|
||||
self.emit_unlabled_cf_in_while_condition(e.span, "break");
|
||||
ast::DUMMY_NODE_ID
|
||||
},
|
||||
Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
|
||||
};
|
||||
|
||||
if opt_expr.is_some() {
|
||||
let loop_kind = if label.loop_id == ast::DUMMY_NODE_ID {
|
||||
let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
|
||||
None
|
||||
} else {
|
||||
Some(match self.hir_map.expect_expr(label.loop_id).node {
|
||||
Some(match self.hir_map.expect_expr(loop_id).node {
|
||||
hir::ExprWhile(..) => LoopKind::WhileLoop,
|
||||
hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
|
||||
ref r => span_bug!(e.span,
|
||||
|
|
@ -110,9 +120,15 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.require_loop("break", e.span);
|
||||
}
|
||||
hir::ExprAgain(_) => self.require_loop("continue", e.span),
|
||||
hir::ExprAgain(label) => {
|
||||
if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.loop_id.into() {
|
||||
self.emit_unlabled_cf_in_while_condition(e.span, "continue");
|
||||
}
|
||||
self.require_loop("continue", e.span)
|
||||
},
|
||||
_ => intravisit::walk_expr(self, e),
|
||||
}
|
||||
}
|
||||
|
|
@ -143,4 +159,12 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
|
||||
struct_span_err!(self.sess, span, E0583,
|
||||
"`break` or `continue` with no label in the condition of a `while` loop")
|
||||
.span_label(span,
|
||||
&format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue