Auto merge of #52018 - flip1995:rfc2103, r=oli-obk
Implementation of tool lints. Tracking issue: #44690
This commit is contained in:
commit
3ea16c3493
|
@ -0,0 +1,35 @@
|
||||||
|
# `tool_lints`
|
||||||
|
|
||||||
|
The tracking issue for this feature is: [#44690]
|
||||||
|
|
||||||
|
[#44690]: https://github.com/rust-lang/rust/issues/44690
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of
|
||||||
|
certain tools.
|
||||||
|
|
||||||
|
Currently `clippy` is the only available lint tool.
|
||||||
|
|
||||||
|
It is recommended for lint tools to implement the scoped lints like this:
|
||||||
|
|
||||||
|
- `#[_(TOOL_NAME::lintname)]`: for lint names
|
||||||
|
- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints
|
||||||
|
- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints
|
||||||
|
|
||||||
|
## An example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
|
||||||
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
|
#[allow(clippy::filter_map)]
|
||||||
|
fn main() {
|
||||||
|
let v = vec![0; 10];
|
||||||
|
let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::<Vec<_>>();
|
||||||
|
println!("No filter_map()!");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[^1]: Some defined lint groups can be excluded here.
|
|
@ -2137,4 +2137,5 @@ register_diagnostics! {
|
||||||
E0707, // multiple elided lifetimes used in arguments of `async fn`
|
E0707, // multiple elided lifetimes used in arguments of `async fn`
|
||||||
E0708, // `async` non-`move` closures with arguments are not currently supported
|
E0708, // `async` non-`move` closures with arguments are not currently supported
|
||||||
E0709, // multiple different lifetimes used in arguments of `async fn`
|
E0709, // multiple different lifetimes used in arguments of `async fn`
|
||||||
|
E0710, // an unknown tool name found in scoped lint
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use session::Session;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::codemap::MultiSpan;
|
use syntax::codemap::MultiSpan;
|
||||||
|
use syntax::feature_gate;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use util::nodemap::FxHashMap;
|
use util::nodemap::FxHashMap;
|
||||||
|
|
||||||
|
@ -221,6 +222,28 @@ impl<'a> LintLevelsBuilder<'a> {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if let Some(lint_tool) = word.is_scoped() {
|
||||||
|
if !self.sess.features_untracked().tool_lints {
|
||||||
|
feature_gate::emit_feature_err(&sess.parse_sess,
|
||||||
|
"tool_lints",
|
||||||
|
word.span,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
|
&format!("scoped lint `{}` is experimental",
|
||||||
|
word.ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !attr::is_known_lint_tool(lint_tool) {
|
||||||
|
span_err!(
|
||||||
|
sess,
|
||||||
|
lint_tool.span,
|
||||||
|
E0710,
|
||||||
|
"an unknown tool name found in scoped lint: `{}`",
|
||||||
|
word.ident
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
let name = word.name();
|
let name = word.name();
|
||||||
match store.check_lint_name(&name.as_str()) {
|
match store.check_lint_name(&name.as_str()) {
|
||||||
CheckLintNameResult::Ok(ids) => {
|
CheckLintNameResult::Ok(ids) => {
|
||||||
|
|
|
@ -90,6 +90,7 @@ pub fn is_known(attr: &Attribute) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
|
const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
|
||||||
|
const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];
|
||||||
|
|
||||||
pub fn is_known_tool(attr: &Attribute) -> bool {
|
pub fn is_known_tool(attr: &Attribute) -> bool {
|
||||||
let tool_name =
|
let tool_name =
|
||||||
|
@ -97,6 +98,10 @@ pub fn is_known_tool(attr: &Attribute) -> bool {
|
||||||
RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
|
RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_known_lint_tool(m_item: Ident) -> bool {
|
||||||
|
RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
impl NestedMetaItem {
|
impl NestedMetaItem {
|
||||||
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
|
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
|
||||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||||
|
@ -290,6 +295,14 @@ impl MetaItem {
|
||||||
pub fn is_meta_item_list(&self) -> bool {
|
pub fn is_meta_item_list(&self) -> bool {
|
||||||
self.meta_item_list().is_some()
|
self.meta_item_list().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_scoped(&self) -> Option<Ident> {
|
||||||
|
if self.ident.segments.len() > 1 {
|
||||||
|
Some(self.ident.segments[0].ident)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attribute {
|
impl Attribute {
|
||||||
|
|
|
@ -458,6 +458,8 @@ declare_features! (
|
||||||
|
|
||||||
// Scoped attributes
|
// Scoped attributes
|
||||||
(active, tool_attributes, "1.25.0", Some(44690), None),
|
(active, tool_attributes, "1.25.0", Some(44690), None),
|
||||||
|
// Scoped lints
|
||||||
|
(active, tool_lints, "1.28.0", Some(44690), None),
|
||||||
|
|
||||||
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
|
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
|
||||||
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
|
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
// Don't allow tool_lints, which aren't scoped
|
||||||
|
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
#![deny(unknown_lints)]
|
||||||
|
|
||||||
|
#![deny(clippy)] //~ ERROR: unknown lint: `clippy`
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
|
||||||
|
#![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
|
||||||
|
|
||||||
|
#[allow(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
#![deny(unknown_lints)]
|
||||||
|
|
||||||
|
#[allow(clippy::almost_swapped)]
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
#![feature(rust_2018_preview)]
|
||||||
|
#![deny(unknown_lints)]
|
||||||
|
|
||||||
|
#[allow(clippy::almost_swapped)]
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#[warn(clippy::decimal_literal_representation)]
|
||||||
|
//~^ ERROR scoped lint `clippy::decimal_literal_representation` is experimental
|
||||||
|
fn main() {
|
||||||
|
let a = 65_535;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0658]: scoped lint `clippy::decimal_literal_representation` is experimental (see issue #44690)
|
||||||
|
--> $DIR/feature-gate-tool_lints.rs:11:8
|
||||||
|
|
|
||||||
|
LL | #[warn(clippy::decimal_literal_representation)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(tool_lints)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2018 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.
|
||||||
|
|
||||||
|
#![feature(tool_lints)]
|
||||||
|
|
||||||
|
#[warn(foo::bar)]
|
||||||
|
//~^ ERROR an unknown tool name found in scoped lint: `foo::bar`
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0710]: an unknown tool name found in scoped lint: `foo::bar`
|
||||||
|
--> $DIR/tool_lints.rs:13:8
|
||||||
|
|
|
||||||
|
LL | #[warn(foo::bar)]
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0710`.
|
Loading…
Reference in New Issue