mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Reimplement unused_labels lint as a compiler builtin in the resolver
This commit is contained in:
parent
7676982e90
commit
88f4063c83
@ -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,
|
||||
|
@ -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(),
|
||||
|
@ -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!");
|
||||
|
75
src/test/ui/lint/unused_labels.rs
Normal file
75
src/test/ui/lint/unused_labels.rs
Normal 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
|
||||
}
|
||||
}
|
53
src/test/ui/lint/unused_labels.stderr
Normal file
53
src/test/ui/lint/unused_labels.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user