Reimplement unused_labels lint as a compiler builtin in the resolver

This commit is contained in:
Kyle Stachowicz 2018-05-17 17:20:30 -07:00
parent 7676982e90
commit 88f4063c83
10 changed files with 170 additions and 21 deletions

View File

@ -279,6 +279,12 @@ declare_lint! {
"detects name collision with an existing but unstable method"
}
declare_lint! {
pub UNUSED_LABELS,
Warn,
"detects labels that are never used"
}
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
@ -325,6 +331,7 @@ impl LintPass for HardwiredLints {
UNUSED_MUT,
SINGLE_USE_LIFETIME,
UNUSED_LIFETIME,
UNUSED_LABELS,
TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIME_IN_PATH,
BARE_TRAIT_OBJECT,

View File

@ -142,6 +142,10 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
}
}
for (id, span) in resolver.unused_labels.iter() {
resolver.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
}
let mut visitor = UnusedImportCheckVisitor {
resolver,
unused_imports: NodeMap(),

View File

@ -1473,6 +1473,10 @@ pub struct Resolver<'a> {
pub maybe_unused_trait_imports: NodeSet,
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
/// A list of labels as of yet unused. Labels will be removed from this map when
/// they are used (in a `break` or `continue` statement)
pub unused_labels: FxHashMap<NodeId, Span>,
/// privacy errors are delayed until the end in order to deduplicate them
privacy_errors: Vec<PrivacyError<'a>>,
/// ambiguity errors are delayed for deduplication
@ -1752,6 +1756,8 @@ impl<'a> Resolver<'a> {
maybe_unused_trait_imports: NodeSet(),
maybe_unused_extern_crates: Vec::new(),
unused_labels: FxHashMap(),
privacy_errors: Vec::new(),
ambiguity_errors: Vec::new(),
use_injections: Vec::new(),
@ -3694,6 +3700,7 @@ impl<'a> Resolver<'a> {
where F: FnOnce(&mut Resolver)
{
if let Some(label) = label {
self.unused_labels.insert(id, label.ident.span);
let def = Def::Label(id);
self.with_label_rib(|this| {
this.label_ribs.last_mut().unwrap().bindings.insert(label.ident, def);
@ -3742,9 +3749,10 @@ impl<'a> Resolver<'a> {
ResolutionError::UndeclaredLabel(&label.ident.name.as_str(),
close_match));
}
Some(def @ Def::Label(_)) => {
Some(Def::Label(id)) => {
// Since this def is a label, it is never read.
self.record_def(expr.id, PathResolution::new(def));
self.record_def(expr.id, PathResolution::new(Def::Label(id)));
self.unused_labels.remove(&id);
}
Some(_) => {
span_bug!(expr.span, "label wasn't mapped to a label def!");

View File

@ -0,0 +1,75 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// The output should warn when a loop label is not used. However, it
// should also deal with the edge cases where a label is shadowed,
// within nested loops
// compile-pass
fn main() {
'unused_while_label: while 0 == 0 {
//~^ WARN unused label
}
let opt = Some(0);
'unused_while_let_label: while let Some(_) = opt {
//~^ WARN unused label
}
'unused_for_label: for _ in 0..10 {
//~^ WARN unused label
}
'used_loop_label: loop {
break 'used_loop_label;
}
'used_loop_label_outer_1: for _ in 0..10 {
'used_loop_label_inner_1: for _ in 0..10 {
break 'used_loop_label_inner_1;
}
break 'used_loop_label_outer_1;
}
'used_loop_label_outer_2: for _ in 0..10 {
'unused_loop_label_inner_2: for _ in 0..10 {
//~^ WARN unused label
break 'used_loop_label_outer_2;
}
}
'unused_loop_label_outer_3: for _ in 0..10 {
//~^ WARN unused label
'used_loop_label_inner_3: for _ in 0..10 {
break 'used_loop_label_inner_3;
}
}
// Test breaking many times with the same inner label doesn't break the
// warning on the outer label
'many_used_shadowed: for _ in 0..10 {
//~^ WARN unused label
'many_used_shadowed: for _ in 0..10 {
//~^ WARN label name `'many_used_shadowed` shadows a label name that is already in scope
if 1 % 2 == 0 {
break 'many_used_shadowed;
} else {
break 'many_used_shadowed;
}
}
}
// This is diverging, so put it at the end so we don't get
// unreachable_code errors everywhere else
'unused_loop_label: loop {
//~^ WARN unused label
}
}

View File

@ -0,0 +1,53 @@
warning: unused label
--> $DIR/unused_labels.rs:18:5
|
LL | 'unused_while_label: while 0 == 0 {
| ^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_labels)] on by default
warning: unused label
--> $DIR/unused_labels.rs:23:5
|
LL | 'unused_while_let_label: while let Some(_) = opt {
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused label
--> $DIR/unused_labels.rs:27:5
|
LL | 'unused_for_label: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^
warning: unused label
--> $DIR/unused_labels.rs:43:9
|
LL | 'unused_loop_label_inner_2: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused label
--> $DIR/unused_labels.rs:49:5
|
LL | 'unused_loop_label_outer_3: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused label
--> $DIR/unused_labels.rs:58:5
|
LL | 'many_used_shadowed: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^
warning: unused label
--> $DIR/unused_labels.rs:72:5
|
LL | 'unused_loop_label: loop {
| ^^^^^^^^^^^^^^^^^^
warning: label name `'many_used_shadowed` shadows a label name that is already in scope
--> $DIR/unused_labels.rs:60:9
|
LL | 'many_used_shadowed: for _ in 0..10 {
| ------------------- first declared here
LL | //~^ WARN unused label
LL | 'many_used_shadowed: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^ lifetime 'many_used_shadowed already in scope

View File

@ -18,6 +18,7 @@
// discussed here:
// https://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833
#[allow(unused_labels)]
pub fn foo() {
{ 'fl: for _ in 0..10 { break; } }
{ 'fl: loop { break; } } //~ WARN label name `'fl` shadows a label name that is already in scope

View File

@ -1,5 +1,5 @@
warning: label name `'fl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:23:7
--> $DIR/loops-reject-duplicate-labels-2.rs:24:7
|
LL | { 'fl: for _ in 0..10 { break; } }
| --- first declared here
@ -7,7 +7,7 @@ LL | { 'fl: loop { break; } } //~ WARN label name `'fl` shadows
| ^^^ lifetime 'fl already in scope
warning: label name `'lf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:25:7
--> $DIR/loops-reject-duplicate-labels-2.rs:26:7
|
LL | { 'lf: loop { break; } }
| --- first declared here
@ -15,7 +15,7 @@ LL | { 'lf: for _ in 0..10 { break; } } //~ WARN label name `'lf` shadows
| ^^^ lifetime 'lf already in scope
warning: label name `'wl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:27:7
--> $DIR/loops-reject-duplicate-labels-2.rs:28:7
|
LL | { 'wl: while 2 > 1 { break; } }
| --- first declared here
@ -23,7 +23,7 @@ LL | { 'wl: loop { break; } } //~ WARN label name `'wl` shadows
| ^^^ lifetime 'wl already in scope
warning: label name `'lw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:29:7
--> $DIR/loops-reject-duplicate-labels-2.rs:30:7
|
LL | { 'lw: loop { break; } }
| --- first declared here
@ -31,7 +31,7 @@ LL | { 'lw: while 2 > 1 { break; } } //~ WARN label name `'lw` shadows
| ^^^ lifetime 'lw already in scope
warning: label name `'fw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:31:7
--> $DIR/loops-reject-duplicate-labels-2.rs:32:7
|
LL | { 'fw: for _ in 0..10 { break; } }
| --- first declared here
@ -39,7 +39,7 @@ LL | { 'fw: while 2 > 1 { break; } } //~ WARN label name `'fw` shadows
| ^^^ lifetime 'fw already in scope
warning: label name `'wf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:33:7
--> $DIR/loops-reject-duplicate-labels-2.rs:34:7
|
LL | { 'wf: while 2 > 1 { break; } }
| --- first declared here
@ -47,7 +47,7 @@ LL | { 'wf: for _ in 0..10 { break; } } //~ WARN label name `'wf` shadows
| ^^^ lifetime 'wf already in scope
warning: label name `'tl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:35:7
--> $DIR/loops-reject-duplicate-labels-2.rs:36:7
|
LL | { 'tl: while let Some(_) = None::<i32> { break; } }
| --- first declared here
@ -55,7 +55,7 @@ LL | { 'tl: loop { break; } } //~ WARN label name `'tl` shadows
| ^^^ lifetime 'tl already in scope
warning: label name `'lt` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:37:7
--> $DIR/loops-reject-duplicate-labels-2.rs:38:7
|
LL | { 'lt: loop { break; } }
| --- first declared here
@ -63,7 +63,7 @@ LL | { 'lt: while let Some(_) = None::<i32> { break; } }
| ^^^ lifetime 'lt already in scope
error: compilation successful
--> $DIR/loops-reject-duplicate-labels-2.rs:42:1
--> $DIR/loops-reject-duplicate-labels-2.rs:43:1
|
LL | / pub fn main() { //~ ERROR compilation successful
LL | | foo();

View File

@ -15,6 +15,7 @@
// Issue #21633: reject duplicate loop labels in function bodies.
// This is testing the exact cases that are in the issue description.
#[allow(unused_labels)]
fn foo() {
'fl: for _ in 0..10 { break; }
'fl: loop { break; } //~ WARN label name `'fl` shadows a label name that is already in scope

View File

@ -1,5 +1,5 @@
warning: label name `'fl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:20:5
--> $DIR/loops-reject-duplicate-labels.rs:21:5
|
LL | 'fl: for _ in 0..10 { break; }
| --- first declared here
@ -7,7 +7,7 @@ LL | 'fl: loop { break; } //~ WARN label name `'fl` shadows a labe
| ^^^ lifetime 'fl already in scope
warning: label name `'lf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:23:5
--> $DIR/loops-reject-duplicate-labels.rs:24:5
|
LL | 'lf: loop { break; }
| --- first declared here
@ -15,7 +15,7 @@ LL | 'lf: for _ in 0..10 { break; } //~ WARN label name `'lf` shadows a labe
| ^^^ lifetime 'lf already in scope
warning: label name `'wl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:25:5
--> $DIR/loops-reject-duplicate-labels.rs:26:5
|
LL | 'wl: while 2 > 1 { break; }
| --- first declared here
@ -23,7 +23,7 @@ LL | 'wl: loop { break; } //~ WARN label name `'wl` shadows a labe
| ^^^ lifetime 'wl already in scope
warning: label name `'lw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:27:5
--> $DIR/loops-reject-duplicate-labels.rs:28:5
|
LL | 'lw: loop { break; }
| --- first declared here
@ -31,7 +31,7 @@ LL | 'lw: while 2 > 1 { break; } //~ WARN label name `'lw` shadows a labe
| ^^^ lifetime 'lw already in scope
warning: label name `'fw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:29:5
--> $DIR/loops-reject-duplicate-labels.rs:30:5
|
LL | 'fw: for _ in 0..10 { break; }
| --- first declared here
@ -39,7 +39,7 @@ LL | 'fw: while 2 > 1 { break; } //~ WARN label name `'fw` shadows a labe
| ^^^ lifetime 'fw already in scope
warning: label name `'wf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:31:5
--> $DIR/loops-reject-duplicate-labels.rs:32:5
|
LL | 'wf: while 2 > 1 { break; }
| --- first declared here
@ -47,7 +47,7 @@ LL | 'wf: for _ in 0..10 { break; } //~ WARN label name `'wf` shadows a labe
| ^^^ lifetime 'wf already in scope
warning: label name `'tl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:33:5
--> $DIR/loops-reject-duplicate-labels.rs:34:5
|
LL | 'tl: while let Some(_) = None::<i32> { break; }
| --- first declared here
@ -55,7 +55,7 @@ LL | 'tl: loop { break; } //~ WARN label name `'tl` shadows a labe
| ^^^ lifetime 'tl already in scope
warning: label name `'lt` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:35:5
--> $DIR/loops-reject-duplicate-labels.rs:36:5
|
LL | 'lt: loop { break; }
| --- first declared here
@ -63,7 +63,7 @@ LL | 'lt: while let Some(_) = None::<i32> { break; }
| ^^^ lifetime 'lt already in scope
error: compilation successful
--> $DIR/loops-reject-duplicate-labels.rs:49:1
--> $DIR/loops-reject-duplicate-labels.rs:50:1
|
LL | / pub fn main() { //~ ERROR compilation successful
LL | | let s = S;

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(unreachable_code)]
#[allow(unreachable_code, unused_labels)]
fn main() {
'foo: loop {
break 'fo; //~ ERROR use of undeclared label