Implement initernal lint LINT_PASS_IMPL_WITHOUT_MACRO
This commit is contained in:
parent
3cc3486733
commit
7d0a952e46
5 changed files with 87 additions and 17 deletions
|
@ -1341,6 +1341,7 @@ struct LateLintPassObjects<'a> {
|
||||||
lints: &'a mut [LateLintPassObject],
|
lints: &'a mut [LateLintPassObject],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))]
|
||||||
impl LintPass for LateLintPassObjects<'_> {
|
impl LintPass for LateLintPassObjects<'_> {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
|
@ -1510,6 +1511,7 @@ struct EarlyLintPassObjects<'a> {
|
||||||
lints: &'a mut [EarlyLintPassObject],
|
lints: &'a mut [EarlyLintPassObject],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))]
|
||||||
impl LintPass for EarlyLintPassObjects<'_> {
|
impl LintPass for EarlyLintPassObjects<'_> {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::lint::{
|
||||||
};
|
};
|
||||||
use errors::Applicability;
|
use errors::Applicability;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use syntax::ast::Ident;
|
use syntax::ast::{Ident, Item, ItemKind};
|
||||||
use syntax::symbol::{sym, Symbol};
|
use syntax::symbol::{sym, Symbol};
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
|
@ -36,10 +36,7 @@ impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
|
||||||
impl EarlyLintPass for DefaultHashTypes {
|
impl EarlyLintPass for DefaultHashTypes {
|
||||||
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
|
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
|
||||||
if let Some(replace) = self.map.get(&ident.name) {
|
if let Some(replace) = self.map.get(&ident.name) {
|
||||||
let msg = format!(
|
let msg = format!("Prefer {} over {}, it has better performance", replace, ident);
|
||||||
"Prefer {} over {}, it has better performance",
|
|
||||||
replace, ident
|
|
||||||
);
|
|
||||||
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
|
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
|
||||||
db.span_suggestion(
|
db.span_suggestion(
|
||||||
ident.span,
|
ident.span,
|
||||||
|
@ -47,11 +44,8 @@ impl EarlyLintPass for DefaultHashTypes {
|
||||||
replace.to_string(),
|
replace.to_string(),
|
||||||
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
|
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
|
||||||
);
|
);
|
||||||
db.note(&format!(
|
db.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace))
|
||||||
"a `use rustc_data_structures::fx::{}` may be necessary",
|
.emit();
|
||||||
replace
|
|
||||||
))
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,13 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Rptr(
|
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::MutImmutable }) => {
|
||||||
_,
|
|
||||||
MutTy {
|
|
||||||
ty: inner_ty,
|
|
||||||
mutbl: Mutability::MutImmutable,
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
|
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() {
|
if cx.tcx.impl_trait_ref(impl_did).is_some() {
|
||||||
return;
|
return;
|
||||||
|
@ -225,3 +213,31 @@ fn gen_args(segment: &PathSegment) -> String {
|
||||||
|
|
||||||
String::new()
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -493,6 +493,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||||
|
|
||||||
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
|
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 DefaultHashTypes::new());
|
||||||
|
store.register_early_pass(sess, false, false, box LintPassImpl);
|
||||||
store.register_late_pass(sess, false, false, false, box TyTyKind);
|
store.register_late_pass(sess, false, false, false, box TyTyKind);
|
||||||
store.register_group(
|
store.register_group(
|
||||||
sess,
|
sess,
|
||||||
|
@ -502,6 +503,7 @@ pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||||
vec![
|
vec![
|
||||||
LintId::of(DEFAULT_HASH_TYPES),
|
LintId::of(DEFAULT_HASH_TYPES),
|
||||||
LintId::of(USAGE_OF_TY_TYKIND),
|
LintId::of(USAGE_OF_TY_TYKIND),
|
||||||
|
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||||
LintId::of(TY_PASS_BY_REFERENCE),
|
LintId::of(TY_PASS_BY_REFERENCE),
|
||||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||||
],
|
],
|
||||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue