Skip to content

Commit d67628e

Browse files
committed
Add lint checks for unused loop labels
1 parent 952f344 commit d67628e

File tree

6 files changed

+154
-2
lines changed

6 files changed

+154
-2
lines changed

src/librustc_lint/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
110110

111111
add_early_builtin_with_new!(sess,
112112
DeprecatedAttr,
113+
UnusedLoopLabel,
113114
);
114115

115116
add_builtin!(sess,
@@ -177,7 +178,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
177178
UNUSED_DOC_COMMENT,
178179
UNUSED_EXTERN_CRATES,
179180
UNUSED_FEATURES,
180-
UNUSED_PARENS);
181+
UNUSED_PARENS,
182+
UNUSED_LOOP_LABEL);
181183

182184
add_lint_group!(sess,
183185
"rust_2018_idioms",

src/librustc_lint/unused.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use syntax_pos::Span;
2525

2626
use rustc::hir;
2727

28+
use std::vec;
29+
2830
declare_lint! {
2931
pub UNUSED_MUST_USE,
3032
Warn,
@@ -464,3 +466,64 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
464466
}
465467
}
466468
}
469+
470+
declare_lint! {
471+
pub(super) UNUSED_LOOP_LABEL,
472+
Warn,
473+
"warns on unused labels for loops"
474+
}
475+
476+
#[derive(Clone)]
477+
pub struct UnusedLoopLabel(pub vec::Vec<ast::Label>);
478+
479+
impl UnusedLoopLabel {
480+
pub fn new() -> Self {
481+
UnusedLoopLabel(vec![])
482+
}
483+
}
484+
485+
impl LintPass for UnusedLoopLabel {
486+
fn get_lints(&self) -> LintArray {
487+
lint_array!(UNUSED_LOOP_LABEL)
488+
}
489+
}
490+
491+
impl EarlyLintPass for UnusedLoopLabel {
492+
fn check_expr(&mut self, _: &EarlyContext, expr: &ast::Expr) {
493+
match expr.node {
494+
ast::ExprKind::While(_, _, Some(ref label))
495+
| ast::ExprKind::WhileLet(_, _, _, Some(ref label))
496+
| ast::ExprKind::ForLoop(_, _, _, Some(ref label))
497+
| ast::ExprKind::Loop(_, Some(ref label)) => {
498+
self.0.push(*label);
499+
}
500+
ast::ExprKind::Break(Some(ref label), _) | ast::ExprKind::Continue(Some(ref label)) => {
501+
'remove_used_label: for i in (0..self.0.len()).rev() {
502+
if self.0.get(i).unwrap().ident.name == label.ident.name {
503+
self.0.remove(i);
504+
break 'remove_used_label;
505+
}
506+
}
507+
}
508+
_ => {}
509+
}
510+
}
511+
512+
fn check_expr_post(&mut self, ctxt: &EarlyContext, expr: &ast::Expr) {
513+
match expr.node {
514+
ast::ExprKind::While(_, _, Some(ref label))
515+
| ast::ExprKind::WhileLet(_, _, _, Some(ref label))
516+
| ast::ExprKind::ForLoop(_, _, _, Some(ref label))
517+
| ast::ExprKind::Loop(_, Some(ref label)) => if !self.0.is_empty() {
518+
{
519+
let unused_label = self.0.last().unwrap();
520+
if label.ident.name == unused_label.ident.name {
521+
ctxt.span_lint(UNUSED_LOOP_LABEL, label.ident.span, "unused loop label");
522+
}
523+
}
524+
self.0.pop();
525+
},
526+
_ => {}
527+
}
528+
}
529+
}

src/librustc_mir/interpret/eval_context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1705,7 +1705,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
17051705
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
17061706
backtrace.resolve();
17071707
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
1708-
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
1708+
for (i, frame) in backtrace.frames().iter().enumerate() {
17091709
if frame.symbols().is_empty() {
17101710
write!(trace_text, "{}: no symbols\n", i).unwrap();
17111711
}

src/test/ui/lint/unused_loop_label.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// The output should warn when a loop label is not used. However, it
12+
// should also deal with the edge cases where a label is shadowed,
13+
// within nested loops
14+
15+
// compile-pass
16+
// compile-flags: -W unused_loop_label
17+
18+
fn main() {
19+
'unused_while_label: while 0 == 0 {
20+
//~^ WARN unused loop label
21+
}
22+
23+
let opt = Some(0);
24+
'unused_while_let_label: while let Some(_) = opt {
25+
//~^ WARN unused loop label
26+
}
27+
28+
'unused_for_label: for _ in 0..10 {
29+
//~^ WARN unused loop label
30+
}
31+
32+
'used_loop_label: loop {
33+
break 'used_loop_label;
34+
}
35+
36+
'used_loop_label_outer: loop {
37+
'used_loop_label_inner: loop {
38+
break 'used_loop_label_inner;
39+
}
40+
break 'used_loop_label_outer;
41+
}
42+
43+
'unused_loop_label_outer: loop {
44+
'unused_loop_label_inner: loop {
45+
//~^ WARN unused loop label
46+
break 'unused_loop_label_outer;
47+
}
48+
}
49+
50+
// This is diverging, so put it at the end so we don't get unreachable_code errors everywhere
51+
// else
52+
'unused_loop_label: loop {
53+
//~^ WARN unused loop label
54+
}
55+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
warning: unused loop label
2+
--> $DIR/unused_loop_label.rs:19:5
3+
|
4+
LL | 'unused_while_label: while 0 == 0 {
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: requested on the command line with `-W unused-loop-label`
8+
9+
warning: unused loop label
10+
--> $DIR/unused_loop_label.rs:24:5
11+
|
12+
LL | 'unused_while_let_label: while let Some(_) = opt {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: unused loop label
16+
--> $DIR/unused_loop_label.rs:28:5
17+
|
18+
LL | 'unused_for_label: for _ in 0..10 {
19+
| ^^^^^^^^^^^^^^^^^
20+
21+
warning: unused loop label
22+
--> $DIR/unused_loop_label.rs:44:9
23+
|
24+
LL | 'unused_loop_label_inner: loop {
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^
26+
27+
warning: unused loop label
28+
--> $DIR/unused_loop_label.rs:52:5
29+
|
30+
LL | 'unused_loop_label: loop {
31+
| ^^^^^^^^^^^^^^^^^^
32+

src/test/ui/lint/unused_loop_label.stdout

Whitespace-only changes.

0 commit comments

Comments
 (0)