Skip to content

Commit 3ea16c3

Browse files
committed
Auto merge of #52018 - flip1995:rfc2103, r=oli-obk
Implementation of tool lints. Tracking issue: #44690
2 parents 062a416 + c394900 commit 3ea16c3

14 files changed

+201
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# `tool_lints`
2+
3+
The tracking issue for this feature is: [#44690]
4+
5+
[#44690]: https://github.com/rust-lang/rust/issues/44690
6+
7+
------------------------
8+
9+
Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of
10+
certain tools.
11+
12+
Currently `clippy` is the only available lint tool.
13+
14+
It is recommended for lint tools to implement the scoped lints like this:
15+
16+
- `#[_(TOOL_NAME::lintname)]`: for lint names
17+
- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints
18+
- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints
19+
20+
## An example
21+
22+
```rust
23+
#![feature(tool_lints)]
24+
25+
#![warn(clippy::pedantic)]
26+
27+
#[allow(clippy::filter_map)]
28+
fn main() {
29+
let v = vec![0; 10];
30+
let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::<Vec<_>>();
31+
println!("No filter_map()!");
32+
}
33+
```
34+
35+
[^1]: Some defined lint groups can be excluded here.

src/librustc/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2137,4 +2137,5 @@ register_diagnostics! {
21372137
E0707, // multiple elided lifetimes used in arguments of `async fn`
21382138
E0708, // `async` non-`move` closures with arguments are not currently supported
21392139
E0709, // multiple different lifetimes used in arguments of `async fn`
2140+
E0710, // an unknown tool name found in scoped lint
21402141
}

src/librustc/lint/levels.rs

+23
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use session::Session;
2222
use syntax::ast;
2323
use syntax::attr;
2424
use syntax::codemap::MultiSpan;
25+
use syntax::feature_gate;
2526
use syntax::symbol::Symbol;
2627
use util::nodemap::FxHashMap;
2728

@@ -221,6 +222,28 @@ impl<'a> LintLevelsBuilder<'a> {
221222
continue
222223
}
223224
};
225+
if let Some(lint_tool) = word.is_scoped() {
226+
if !self.sess.features_untracked().tool_lints {
227+
feature_gate::emit_feature_err(&sess.parse_sess,
228+
"tool_lints",
229+
word.span,
230+
feature_gate::GateIssue::Language,
231+
&format!("scoped lint `{}` is experimental",
232+
word.ident));
233+
}
234+
235+
if !attr::is_known_lint_tool(lint_tool) {
236+
span_err!(
237+
sess,
238+
lint_tool.span,
239+
E0710,
240+
"an unknown tool name found in scoped lint: `{}`",
241+
word.ident
242+
);
243+
}
244+
245+
continue
246+
}
224247
let name = word.name();
225248
match store.check_lint_name(&name.as_str()) {
226249
CheckLintNameResult::Ok(ids) => {

src/libsyntax/attr/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,18 @@ pub fn is_known(attr: &Attribute) -> bool {
9090
}
9191

9292
const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
93+
const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];
9394

9495
pub fn is_known_tool(attr: &Attribute) -> bool {
9596
let tool_name =
9697
attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
9798
RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
9899
}
99100

101+
pub fn is_known_lint_tool(m_item: Ident) -> bool {
102+
RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref())
103+
}
104+
100105
impl NestedMetaItem {
101106
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
102107
pub fn meta_item(&self) -> Option<&MetaItem> {
@@ -290,6 +295,14 @@ impl MetaItem {
290295
pub fn is_meta_item_list(&self) -> bool {
291296
self.meta_item_list().is_some()
292297
}
298+
299+
pub fn is_scoped(&self) -> Option<Ident> {
300+
if self.ident.segments.len() > 1 {
301+
Some(self.ident.segments[0].ident)
302+
} else {
303+
None
304+
}
305+
}
293306
}
294307

295308
impl Attribute {

src/libsyntax/feature_gate.rs

+2
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,8 @@ declare_features! (
458458

459459
// Scoped attributes
460460
(active, tool_attributes, "1.25.0", Some(44690), None),
461+
// Scoped lints
462+
(active, tool_lints, "1.28.0", Some(44690), None),
461463

462464
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
463465
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2018 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+
#[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
12+
fn main() {}

src/test/compile-fail/tool_lints.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2018 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+
// Don't allow tool_lints, which aren't scoped
12+
13+
#![feature(tool_lints)]
14+
#![deny(unknown_lints)]
15+
16+
#![deny(clippy)] //~ ERROR: unknown lint: `clippy`
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 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+
#![feature(tool_lints)]
12+
13+
#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
14+
15+
#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
16+
fn main() {}

src/test/run-pass/tool_lints.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2018 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+
#![feature(tool_lints)]
12+
#![deny(unknown_lints)]
13+
14+
#[allow(clippy::almost_swapped)]
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 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+
#![feature(tool_lints)]
12+
#![feature(rust_2018_preview)]
13+
#![deny(unknown_lints)]
14+
15+
#[allow(clippy::almost_swapped)]
16+
fn main() {}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2018 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+
#[warn(clippy::decimal_literal_representation)]
12+
//~^ ERROR scoped lint `clippy::decimal_literal_representation` is experimental
13+
fn main() {
14+
let a = 65_535;
15+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: scoped lint `clippy::decimal_literal_representation` is experimental (see issue #44690)
2+
--> $DIR/feature-gate-tool_lints.rs:11:8
3+
|
4+
LL | #[warn(clippy::decimal_literal_representation)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(tool_lints)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/tool_lints.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2018 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+
#![feature(tool_lints)]
12+
13+
#[warn(foo::bar)]
14+
//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
15+
fn main() {}

src/test/ui/tool_lints.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
2+
--> $DIR/tool_lints.rs:13:8
3+
|
4+
LL | #[warn(foo::bar)]
5+
| ^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0710`.

0 commit comments

Comments
 (0)