Skip to content

Commit be140e9

Browse files
committed
Lint unused labels
1 parent e4b3cbb commit be140e9

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
88
[Jump to usage instructions](#usage)
99

1010
##Lints
11-
There are 129 lints included in this crate:
11+
There are 130 lints included in this crate:
1212

1313
name | default | meaning
1414
---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -129,6 +129,7 @@ name
129129
[unstable_as_mut_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_mut_slice) | warn | as_mut_slice is not stable and can be replaced by &mut v[..]see https://github.com/rust-lang/rust/issues/27729
130130
[unstable_as_slice](https://github.com/Manishearth/rust-clippy/wiki#unstable_as_slice) | warn | as_slice is not stable and can be replaced by & v[..]see https://github.com/rust-lang/rust/issues/27729
131131
[unused_collect](https://github.com/Manishearth/rust-clippy/wiki#unused_collect) | warn | `collect()`ing an iterator without using the result; this is usually better written as a for loop
132+
[unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label
132133
[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions
133134
[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting
134135
[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub mod temporary_assignment;
9393
pub mod transmute;
9494
pub mod types;
9595
pub mod unicode;
96+
pub mod unused_label;
9697
pub mod vec;
9798
pub mod zero_div_zero;
9899
// end lints modules, do not remove this comment, it’s used in `update_lints`
@@ -173,6 +174,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
173174
reg.register_early_lint_pass(box formatting::Formatting);
174175
reg.register_late_lint_pass(box swap::Swap);
175176
reg.register_early_lint_pass(box if_not_else::IfNotElse);
177+
reg.register_late_lint_pass(box unused_label::UnusedLabel::new());
176178

177179
reg.register_lint_group("clippy_pedantic", vec![
178180
enum_glob_use::ENUM_GLOB_USE,
@@ -305,6 +307,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
305307
types::TYPE_COMPLEXITY,
306308
types::UNIT_CMP,
307309
unicode::ZERO_WIDTH_SPACE,
310+
unused_label::UNUSED_LABEL,
308311
vec::USELESS_VEC,
309312
zero_div_zero::ZERO_DIVIDED_BY_ZERO,
310313
]);

src/unused_label.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use rustc::lint::*;
2+
use rustc_front::hir;
3+
use rustc_front::intravisit::FnKind;
4+
use std::collections::{HashMap, HashSet};
5+
use syntax::ast;
6+
use syntax::codemap::Span;
7+
use syntax::parse::token::InternedString;
8+
use utils::span_lint;
9+
10+
/// **What it does:** This lint checks for unused labels.
11+
///
12+
/// **Why is this bad?** Maybe the label should be used in which case there is an error in the
13+
/// code or it should be removed.
14+
///
15+
/// **Known problems:** Hopefully none.
16+
///
17+
/// **Example:**
18+
/// ```rust,ignore
19+
/// fn unused_label() {
20+
/// 'label: for i in 1..2 {
21+
/// if i > 4 { continue }
22+
/// }
23+
/// ```
24+
declare_lint! {
25+
pub UNUSED_LABEL,
26+
Warn,
27+
"unused label"
28+
}
29+
30+
pub struct UnusedLabel {
31+
declared_labels: HashMap<InternedString, Span>,
32+
used_labels: HashSet<InternedString>,
33+
}
34+
35+
impl UnusedLabel {
36+
pub fn new() -> UnusedLabel {
37+
UnusedLabel {
38+
declared_labels: HashMap::new(),
39+
used_labels: HashSet::new(),
40+
}
41+
}
42+
}
43+
44+
impl LintPass for UnusedLabel {
45+
fn get_lints(&self) -> LintArray {
46+
lint_array!(UNUSED_LABEL)
47+
}
48+
}
49+
50+
impl LateLintPass for UnusedLabel {
51+
fn check_fn(&mut self, _: &LateContext, _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) {
52+
self.declared_labels.clear();
53+
self.used_labels.clear();
54+
}
55+
56+
fn check_expr(&mut self, _: &LateContext, expr: &hir::Expr) {
57+
match expr.node {
58+
hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => {
59+
self.used_labels.insert(label.node.name.as_str());
60+
}
61+
hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => {
62+
self.declared_labels.insert(label.name.as_str(), expr.span);
63+
}
64+
_ => (),
65+
}
66+
}
67+
68+
fn check_fn_post(&mut self, cx: &LateContext, _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) {
69+
for (label, span) in &self.declared_labels {
70+
if !self.used_labels.contains(label) {
71+
span_lint(cx, UNUSED_LABEL, *span, &format!("unused label `{}`", label));
72+
}
73+
}
74+
}
75+
}

tests/compile-fail/unused_labels.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![plugin(clippy)]
2+
#![feature(plugin)]
3+
4+
#![deny(unused_label)]
5+
#![allow(dead_code)]
6+
7+
fn unused_label() {
8+
'label: for i in 1..2 { //~ERROR: unused label `'label`
9+
if i > 4 { continue }
10+
}
11+
}
12+
13+
fn foo() {
14+
'same_label_in_two_fns: loop {
15+
break 'same_label_in_two_fns;
16+
}
17+
}
18+
19+
fn main() {
20+
'a: for _ in 0..10 {
21+
while let Some(42) = None {
22+
continue 'a;
23+
}
24+
}
25+
26+
'same_label_in_two_fns: loop { //~ERROR: unused label `'same_label_in_two_fns`
27+
let _ = 1;
28+
}
29+
}

0 commit comments

Comments
 (0)