Only allow {declare,impl}_lint_pass macros for implementing LintPass
This commit is contained in:
parent
7d0a952e46
commit
37f09cb237
4 changed files with 57 additions and 11 deletions
|
@ -9,6 +9,7 @@ use errors::Applicability;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use syntax::ast::{Ident, Item, ItemKind};
|
use syntax::ast::{Ident, Item, ItemKind};
|
||||||
use syntax::symbol::{sym, Symbol};
|
use syntax::symbol::{sym, Symbol};
|
||||||
|
use syntax_pos::ExpnInfo;
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub DEFAULT_HASH_TYPES,
|
pub DEFAULT_HASH_TYPES,
|
||||||
|
@ -225,19 +226,32 @@ declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
|
||||||
impl EarlyLintPass for LintPassImpl {
|
impl EarlyLintPass for LintPassImpl {
|
||||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
|
||||||
if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
|
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 let Some(last) = lint_pass.path.segments.last() {
|
if last.ident.name == sym::LintPass {
|
||||||
if last.ident.as_str() == "LintPass" {
|
match &lint_pass.path.span.ctxt().outer_expn_info() {
|
||||||
cx.struct_span_lint(
|
Some(info) if is_lint_pass_expansion(info) => {}
|
||||||
LINT_PASS_IMPL_WITHOUT_MACRO,
|
_ => {
|
||||||
lint_pass.path.span,
|
cx.struct_span_lint(
|
||||||
"implementing `LintPass` by hand",
|
LINT_PASS_IMPL_WITHOUT_MACRO,
|
||||||
)
|
lint_pass.path.span,
|
||||||
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
|
"implementing `LintPass` by hand",
|
||||||
.emit();
|
)
|
||||||
|
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
|
||||||
|
if expn_info.format.name() == sym::impl_lint_pass {
|
||||||
|
true
|
||||||
|
} else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
|
||||||
|
info.format.name() == sym::declare_lint_pass
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ symbols! {
|
||||||
custom_inner_attributes,
|
custom_inner_attributes,
|
||||||
custom_test_frameworks,
|
custom_test_frameworks,
|
||||||
c_variadic,
|
c_variadic,
|
||||||
|
declare_lint_pass,
|
||||||
decl_macro,
|
decl_macro,
|
||||||
Default,
|
Default,
|
||||||
default_lib_allocator,
|
default_lib_allocator,
|
||||||
|
@ -324,6 +325,7 @@ symbols! {
|
||||||
if_while_or_patterns,
|
if_while_or_patterns,
|
||||||
ignore,
|
ignore,
|
||||||
impl_header_lifetime_elision,
|
impl_header_lifetime_elision,
|
||||||
|
impl_lint_pass,
|
||||||
impl_trait_in_bindings,
|
impl_trait_in_bindings,
|
||||||
import_shadowing,
|
import_shadowing,
|
||||||
index,
|
index,
|
||||||
|
@ -365,6 +367,7 @@ symbols! {
|
||||||
link_llvm_intrinsics,
|
link_llvm_intrinsics,
|
||||||
link_name,
|
link_name,
|
||||||
link_section,
|
link_section,
|
||||||
|
LintPass,
|
||||||
lint_reasons,
|
lint_reasons,
|
||||||
literal,
|
literal,
|
||||||
local_inner_macros,
|
local_inner_macros,
|
||||||
|
|
|
@ -26,6 +26,24 @@ impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! custom_lint_pass_macro {
|
||||||
|
() => {
|
||||||
|
struct Custom;
|
||||||
|
|
||||||
|
impl LintPass for Custom { //~ERROR implementing `LintPass` by hand
|
||||||
|
fn get_lints(&self) -> LintArray {
|
||||||
|
lint_array!(TEST_LINT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"Custom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_lint_pass_macro!();
|
||||||
|
|
||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl_lint_pass!(Bar => [TEST_LINT]);
|
impl_lint_pass!(Bar => [TEST_LINT]);
|
||||||
|
|
|
@ -11,5 +11,16 @@ LL | #![deny(lint_pass_impl_without_macro)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: implementing `LintPass` by hand
|
||||||
|
--> $DIR/lint_pass_impl_without_macro.rs:33:14
|
||||||
|
|
|
||||||
|
LL | impl LintPass for Custom {
|
||||||
|
| ^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | custom_lint_pass_macro!();
|
||||||
|
| -------------------------- in this macro invocation
|
||||||
|
|
|
||||||
|
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue