Skip to content

Commit

Permalink
Auto merge of #52018 - flip1995:rfc2103, r=oli-obk
Browse files Browse the repository at this point in the history
Implementation of tool lints.

Tracking issue: #44690
  • Loading branch information
bors committed Jul 6, 2018
2 parents 062a416 + c394900 commit 3ea16c3
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/doc/unstable-book/src/language-features/tool-lints.md
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2137,4 +2137,5 @@ register_diagnostics! {
E0707, // multiple elided lifetimes used in arguments of `async fn`
E0708, // `async` non-`move` closures with arguments are not currently supported
E0709, // multiple different lifetimes used in arguments of `async fn`
E0710, // an unknown tool name found in scoped lint
}
23 changes: 23 additions & 0 deletions src/librustc/lint/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use session::Session;
use syntax::ast;
use syntax::attr;
use syntax::codemap::MultiSpan;
use syntax::feature_gate;
use syntax::symbol::Symbol;
use util::nodemap::FxHashMap;

Expand Down Expand Up @@ -221,6 +222,28 @@ impl<'a> LintLevelsBuilder<'a> {
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();
match store.check_lint_name(&name.as_str()) {
CheckLintNameResult::Ok(ids) => {
Expand Down
13 changes: 13 additions & 0 deletions src/libsyntax/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,18 @@ pub fn is_known(attr: &Attribute) -> bool {
}

const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];

pub fn is_known_tool(attr: &Attribute) -> bool {
let tool_name =
attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
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 {
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
pub fn meta_item(&self) -> Option<&MetaItem> {
Expand Down Expand Up @@ -290,6 +295,14 @@ impl MetaItem {
pub fn is_meta_item_list(&self) -> bool {
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 {
Expand Down
2 changes: 2 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ declare_features! (

// Scoped attributes
(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)
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
Expand Down
12 changes: 12 additions & 0 deletions src/test/compile-fail/feature-gate-tool_lints.rs
Original file line number Diff line number Diff line change
@@ -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() {}
18 changes: 18 additions & 0 deletions src/test/compile-fail/tool_lints.rs
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/compile-fail/unknown-lint-tool-name.rs
Original file line number Diff line number Diff line change
@@ -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() {}
15 changes: 15 additions & 0 deletions src/test/run-pass/tool_lints.rs
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/run-pass/tool_lints_2018_preview.rs
Original file line number Diff line number Diff line change
@@ -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() {}
15 changes: 15 additions & 0 deletions src/test/ui/feature-gate-tool_lints.rs
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions src/test/ui/feature-gate-tool_lints.stderr
Original file line number Diff line number Diff line change
@@ -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`.
15 changes: 15 additions & 0 deletions src/test/ui/tool_lints.rs
Original file line number Diff line number Diff line change
@@ -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() {}
9 changes: 9 additions & 0 deletions src/test/ui/tool_lints.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 3ea16c3

Please sign in to comment.