diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index eaff87e78f8b..207dc40fa1d7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -48,6 +48,7 @@ // Currently, categories "style", "correctness", "complexity" and "perf" are enabled by default, // as said in the README.md of this repository. If this changes, please update README.md. +#[macro_export] macro_rules! declare_clippy_lint { { pub $name:tt, style, $description:tt } => { declare_tool_lint! { pub clippy::$name, Warn, $description, report_in_external_macro: true } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index a123415cca9d..145faf0b6b65 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -329,7 +329,8 @@ fn get_lints(&self) -> LintArray { lint_array!( UNREADABLE_LITERAL, INCONSISTENT_DIGIT_GROUPING, - LARGE_DIGIT_GROUPS + LARGE_DIGIT_GROUPS, + MISTYPED_LITERAL_SUFFIXES, ) } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 3a0d056bbb5d..879157ec8a47 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -9,12 +9,13 @@ use crate::utils::{ - match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, + match_def_path, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use crate::rustc::hir::*; +use crate::rustc::hir::def::Def; use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -160,15 +161,21 @@ fn get_lints(&self) -> LintArray { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let hir::ItemKind::Static(ref ty, MutImmutable, body_id) = item.node { - if is_lint_ref_type(ty) { + if let hir::ItemKind::Static(ref ty, MutImmutable, _) = item.node { + if is_lint_ref_type(cx, ty) { self.declared_lints.insert(item.name, item.span); - } else if is_lint_array_type(ty) && item.name == "ARRAY" { - if let VisibilityKind::Inherited = item.vis.node { + } + } else if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node { + if_chain! { + if let hir::TraitRef{path, ..} = trait_ref; + if let Def::Trait(def_id) = path.def; + if match_def_path(cx.tcx, def_id, &paths::LINT_PASS); + then { let mut collector = LintCollector { output: &mut self.registered_lints, cx, }; + let body_id = cx.tcx.hir.body_owned_by(impl_item_refs[0].id.node_id); collector.visit_expr(&cx.tcx.hir.body(body_id).value); } } @@ -203,28 +210,22 @@ fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate) { } } -fn is_lint_ref_type(ty: &Ty) -> bool { +fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool { if let TyKind::Rptr( _, MutTy { ty: ref inner, mutbl: MutImmutable, }, - ) = ty.node - { + ) = ty.node { if let TyKind::Path(ref path) = inner.node { - return match_qpath(path, &paths::LINT); + if let Def::Struct(def_id) = cx.tables.qpath_def(path, inner.hir_id) { + return match_def_path(cx.tcx, def_id, &paths::LINT); + } } } - false -} -fn is_lint_array_type(ty: &Ty) -> bool { - if let TyKind::Path(ref path) = ty.node { - match_qpath(path, &paths::LINT_ARRAY) - } else { - false - } + false } struct LintCollector<'a, 'tcx: 'a> { diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 8941d3031562..107a8eea15d7 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -56,7 +56,7 @@ pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; -pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"]; +pub const LINT_PASS: [&str; 3] = ["rustc", "lint", "LintPass"]; pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs new file mode 100644 index 000000000000..c7e11840a37c --- /dev/null +++ b/tests/ui/lint_without_lint_pass.rs @@ -0,0 +1,32 @@ +#![deny(clippy::internal)] + +#![feature(rustc_private)] + +#[macro_use] +extern crate rustc; +use rustc::lint; + +#[macro_use] +extern crate clippy_lints; + +declare_clippy_lint! { + pub TEST_LINT, + correctness, + "" +} + +declare_clippy_lint! { + pub TEST_LINT_REGISTERED, + correctness, + "" +} + +pub struct Pass; +impl lint::LintPass for Pass { + fn get_lints(&self) -> lint::LintArray { + lint_array!(TEST_LINT_REGISTERED) + } +} + +fn main() { +} diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr new file mode 100644 index 000000000000..65d1283a6e34 --- /dev/null +++ b/tests/ui/lint_without_lint_pass.stderr @@ -0,0 +1,20 @@ +error: the lint `TEST_LINT` is not added to any `LintPass` + --> $DIR/lint_without_lint_pass.rs:12:1 + | +12 | / declare_clippy_lint! { +13 | | pub TEST_LINT, +14 | | correctness, +15 | | "" +16 | | } + | |_^ + | +note: lint level defined here + --> $DIR/lint_without_lint_pass.rs:1:9 + | +1 | #![deny(clippy::internal)] + | ^^^^^^^^^^^^^^^^ + = note: #[deny(clippy::lint_without_lint_pass)] implied by #[deny(clippy::internal)] + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error +