about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-06 18:03:46 +0000
committerbors <bors@rust-lang.org>2018-07-06 18:03:46 +0000
commit3ea16c3493d1ed7bb085053d4362907ee8d72366 (patch)
treedfad1902a527dfe48c200010796bbd969310a21d
parent062a416dd4f12cf99b37d078a3da8dd81a1c008e (diff)
parentc3949009adf7e8a039a1f467cbc6e6b5cf993303 (diff)
downloadrust-3ea16c3493d1ed7bb085053d4362907ee8d72366.tar.gz
rust-3ea16c3493d1ed7bb085053d4362907ee8d72366.zip
Auto merge of #52018 - flip1995:rfc2103, r=oli-obk
Implementation of tool lints.

Tracking issue: #44690
-rw-r--r--src/doc/unstable-book/src/language-features/tool-lints.md35
-rw-r--r--src/librustc/diagnostics.rs1
-rw-r--r--src/librustc/lint/levels.rs23
-rw-r--r--src/libsyntax/attr/mod.rs13
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/test/compile-fail/feature-gate-tool_lints.rs12
-rw-r--r--src/test/compile-fail/tool_lints.rs18
-rw-r--r--src/test/compile-fail/unknown-lint-tool-name.rs16
-rw-r--r--src/test/run-pass/tool_lints.rs15
-rw-r--r--src/test/run-pass/tool_lints_2018_preview.rs16
-rw-r--r--src/test/ui/feature-gate-tool_lints.rs15
-rw-r--r--src/test/ui/feature-gate-tool_lints.stderr11
-rw-r--r--src/test/ui/tool_lints.rs15
-rw-r--r--src/test/ui/tool_lints.stderr9
14 files changed, 201 insertions, 0 deletions
diff --git a/src/doc/unstable-book/src/language-features/tool-lints.md b/src/doc/unstable-book/src/language-features/tool-lints.md
new file mode 100644
index 00000000000..5c0d33b5ab0
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/tool-lints.md
@@ -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.
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 5fecf2b1535..5ace8397d9f 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -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
 }
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 3393a2bf89d..5bf15b10715 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -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;
 
@@ -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) => {
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 4e27d6c1525..d746ac3c577 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -90,6 +90,7 @@ 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 =
@@ -97,6 +98,10 @@ pub fn is_known_tool(attr: &Attribute) -> bool {
     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> {
@@ -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 {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 4c883253787..cbc421dbd32 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -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),
diff --git a/src/test/compile-fail/feature-gate-tool_lints.rs b/src/test/compile-fail/feature-gate-tool_lints.rs
new file mode 100644
index 00000000000..c311eb7ed7a
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-tool_lints.rs
@@ -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() {}
diff --git a/src/test/compile-fail/tool_lints.rs b/src/test/compile-fail/tool_lints.rs
new file mode 100644
index 00000000000..ea1efab4cb6
--- /dev/null
+++ b/src/test/compile-fail/tool_lints.rs
@@ -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() {}
diff --git a/src/test/compile-fail/unknown-lint-tool-name.rs b/src/test/compile-fail/unknown-lint-tool-name.rs
new file mode 100644
index 00000000000..78b736edceb
--- /dev/null
+++ b/src/test/compile-fail/unknown-lint-tool-name.rs
@@ -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() {}
diff --git a/src/test/run-pass/tool_lints.rs b/src/test/run-pass/tool_lints.rs
new file mode 100644
index 00000000000..24ec43b12f6
--- /dev/null
+++ b/src/test/run-pass/tool_lints.rs
@@ -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() {}
diff --git a/src/test/run-pass/tool_lints_2018_preview.rs b/src/test/run-pass/tool_lints_2018_preview.rs
new file mode 100644
index 00000000000..6cd57eaa195
--- /dev/null
+++ b/src/test/run-pass/tool_lints_2018_preview.rs
@@ -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() {}
diff --git a/src/test/ui/feature-gate-tool_lints.rs b/src/test/ui/feature-gate-tool_lints.rs
new file mode 100644
index 00000000000..3ef67982be9
--- /dev/null
+++ b/src/test/ui/feature-gate-tool_lints.rs
@@ -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;
+}
diff --git a/src/test/ui/feature-gate-tool_lints.stderr b/src/test/ui/feature-gate-tool_lints.stderr
new file mode 100644
index 00000000000..8019b1e6a28
--- /dev/null
+++ b/src/test/ui/feature-gate-tool_lints.stderr
@@ -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`.
diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs
new file mode 100644
index 00000000000..71f90b17c18
--- /dev/null
+++ b/src/test/ui/tool_lints.rs
@@ -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() {}
diff --git a/src/test/ui/tool_lints.stderr b/src/test/ui/tool_lints.stderr
new file mode 100644
index 00000000000..16468df7370
--- /dev/null
+++ b/src/test/ui/tool_lints.stderr
@@ -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`.