From 7d0a952e465b6584d2a86d2fca3c8a4b077567cd Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 2 May 2019 16:53:12 +0200 Subject: [PATCH] Implement initernal lint LINT_PASS_IMPL_WITHOUT_MACRO --- src/librustc/lint/context.rs | 2 + src/librustc/lint/internal.rs | 50 ++++++++++++------- src/librustc_lint/lib.rs | 2 + .../lint_pass_impl_without_macro.rs | 35 +++++++++++++ .../lint_pass_impl_without_macro.stderr | 15 ++++++ 5 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs create mode 100644 src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7f09120bbdd..7203dd9beaa 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1341,6 +1341,7 @@ struct LateLintPassObjects<'a> { lints: &'a mut [LateLintPassObject], } +#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))] impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() @@ -1510,6 +1511,7 @@ struct EarlyLintPassObjects<'a> { lints: &'a mut [EarlyLintPassObject], } +#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))] impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 86dae579ca7..d3996c4e37a 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -7,7 +7,7 @@ }; use errors::Applicability; use rustc_data_structures::fx::FxHashMap; -use syntax::ast::Ident; +use syntax::ast::{Ident, Item, ItemKind}; use syntax::symbol::{sym, Symbol}; declare_lint! { @@ -36,10 +36,7 @@ pub fn new() -> Self { impl EarlyLintPass for DefaultHashTypes { fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { if let Some(replace) = self.map.get(&ident.name) { - let msg = format!( - "Prefer {} over {}, it has better performance", - replace, ident - ); + let msg = format!("Prefer {} over {}, it has better performance", replace, ident); let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg); db.span_suggestion( ident.span, @@ -47,11 +44,8 @@ fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { replace.to_string(), Applicability::MaybeIncorrect, // FxHashMap, ... needs another import ); - db.note(&format!( - "a `use rustc_data_structures::fx::{}` may be necessary", - replace - )) - .emit(); + db.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + .emit(); } } } @@ -137,13 +131,7 @@ fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) { } } } - TyKind::Rptr( - _, - MutTy { - ty: inner_ty, - mutbl: Mutability::MutImmutable, - }, - ) => { + TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::MutImmutable }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; @@ -225,3 +213,31 @@ fn gen_args(segment: &PathSegment) -> String { String::new() } + +declare_lint! { + pub LINT_PASS_IMPL_WITHOUT_MACRO, + Allow, + "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros" +} + +declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); + +impl EarlyLintPass for LintPassImpl { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node { + if !lint_pass.path.span.ctxt().outer_expn_info().is_some() { + if let Some(last) = lint_pass.path.segments.last() { + if last.ident.as_str() == "LintPass" { + cx.struct_span_lint( + LINT_PASS_IMPL_WITHOUT_MACRO, + lint_pass.path.span, + "implementing `LintPass` by hand", + ) + .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") + .emit(); + } + } + } + } + } +} diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index ec8a9c6fbb2..8a5fde322b2 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -493,6 +493,7 @@ macro_rules! register_passes { pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_early_pass(sess, false, false, box DefaultHashTypes::new()); + store.register_early_pass(sess, false, false, box LintPassImpl); store.register_late_pass(sess, false, false, false, box TyTyKind); store.register_group( sess, @@ -502,6 +503,7 @@ pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) { vec![ LintId::of(DEFAULT_HASH_TYPES), LintId::of(USAGE_OF_TY_TYKIND), + LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), LintId::of(TY_PASS_BY_REFERENCE), LintId::of(USAGE_OF_QUALIFIED_TY), ], diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs new file mode 100644 index 00000000000..92f8e8364a7 --- /dev/null +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -0,0 +1,35 @@ +// compile-flags: -Z unstable-options + +#![feature(rustc_private)] +#![deny(lint_pass_impl_without_macro)] + +extern crate rustc; + +use rustc::lint::{LintArray, LintPass}; +use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array}; + +declare_lint! { + pub TEST_LINT, + Allow, + "test" +} + +struct Foo; + +impl LintPass for Foo { //~ERROR implementing `LintPass` by hand + fn get_lints(&self) -> LintArray { + lint_array!(TEST_LINT) + } + + fn name(&self) -> &'static str { + "Foo" + } +} + +struct Bar; + +impl_lint_pass!(Bar => [TEST_LINT]); + +declare_lint_pass!(Baz => [TEST_LINT]); + +fn main() {} diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr new file mode 100644 index 00000000000..9ddd6af472a --- /dev/null +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr @@ -0,0 +1,15 @@ +error: implementing `LintPass` by hand + --> $DIR/lint_pass_impl_without_macro.rs:19:6 + | +LL | impl LintPass for Foo { + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/lint_pass_impl_without_macro.rs:4:9 + | +LL | #![deny(lint_pass_impl_without_macro)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead + +error: aborting due to previous error + -- 2.44.0