Skip to content

Commit 7d0a952

Browse files
committed
Implement initernal lint LINT_PASS_IMPL_WITHOUT_MACRO
1 parent 3cc3486 commit 7d0a952

File tree

5 files changed

+87
-17
lines changed

5 files changed

+87
-17
lines changed

src/librustc/lint/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,6 +1341,7 @@ struct LateLintPassObjects<'a> {
13411341
lints: &'a mut [LateLintPassObject],
13421342
}
13431343

1344+
#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))]
13441345
impl LintPass for LateLintPassObjects<'_> {
13451346
fn name(&self) -> &'static str {
13461347
panic!()
@@ -1510,6 +1511,7 @@ struct EarlyLintPassObjects<'a> {
15101511
lints: &'a mut [EarlyLintPassObject],
15111512
}
15121513

1514+
#[cfg_attr(not(stage0), allow(lint_pass_impl_without_macro))]
15131515
impl LintPass for EarlyLintPassObjects<'_> {
15141516
fn name(&self) -> &'static str {
15151517
panic!()

src/librustc/lint/internal.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::lint::{
77
};
88
use errors::Applicability;
99
use rustc_data_structures::fx::FxHashMap;
10-
use syntax::ast::Ident;
10+
use syntax::ast::{Ident, Item, ItemKind};
1111
use syntax::symbol::{sym, Symbol};
1212

1313
declare_lint! {
@@ -36,22 +36,16 @@ impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
3636
impl EarlyLintPass for DefaultHashTypes {
3737
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
3838
if let Some(replace) = self.map.get(&ident.name) {
39-
let msg = format!(
40-
"Prefer {} over {}, it has better performance",
41-
replace, ident
42-
);
39+
let msg = format!("Prefer {} over {}, it has better performance", replace, ident);
4340
let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
4441
db.span_suggestion(
4542
ident.span,
4643
"use",
4744
replace.to_string(),
4845
Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
4946
);
50-
db.note(&format!(
51-
"a `use rustc_data_structures::fx::{}` may be necessary",
52-
replace
53-
))
54-
.emit();
47+
db.note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace))
48+
.emit();
5549
}
5650
}
5751
}
@@ -137,13 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
137131
}
138132
}
139133
}
140-
TyKind::Rptr(
141-
_,
142-
MutTy {
143-
ty: inner_ty,
144-
mutbl: Mutability::MutImmutable,
145-
},
146-
) => {
134+
TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::MutImmutable }) => {
147135
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) {
148136
if cx.tcx.impl_trait_ref(impl_did).is_some() {
149137
return;
@@ -225,3 +213,31 @@ fn gen_args(segment: &PathSegment) -> String {
225213

226214
String::new()
227215
}
216+
217+
declare_lint! {
218+
pub LINT_PASS_IMPL_WITHOUT_MACRO,
219+
Allow,
220+
"`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros"
221+
}
222+
223+
declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
224+
225+
impl EarlyLintPass for LintPassImpl {
226+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
227+
if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
228+
if !lint_pass.path.span.ctxt().outer_expn_info().is_some() {
229+
if let Some(last) = lint_pass.path.segments.last() {
230+
if last.ident.as_str() == "LintPass" {
231+
cx.struct_span_lint(
232+
LINT_PASS_IMPL_WITHOUT_MACRO,
233+
lint_pass.path.span,
234+
"implementing `LintPass` by hand",
235+
)
236+
.help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")
237+
.emit();
238+
}
239+
}
240+
}
241+
}
242+
}
243+
}

src/librustc_lint/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
493493

494494
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
495495
store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
496+
store.register_early_pass(sess, false, false, box LintPassImpl);
496497
store.register_late_pass(sess, false, false, false, box TyTyKind);
497498
store.register_group(
498499
sess,
@@ -502,6 +503,7 @@ pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
502503
vec![
503504
LintId::of(DEFAULT_HASH_TYPES),
504505
LintId::of(USAGE_OF_TY_TYKIND),
506+
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
505507
LintId::of(TY_PASS_BY_REFERENCE),
506508
LintId::of(USAGE_OF_QUALIFIED_TY),
507509
],
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// compile-flags: -Z unstable-options
2+
3+
#![feature(rustc_private)]
4+
#![deny(lint_pass_impl_without_macro)]
5+
6+
extern crate rustc;
7+
8+
use rustc::lint::{LintArray, LintPass};
9+
use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array};
10+
11+
declare_lint! {
12+
pub TEST_LINT,
13+
Allow,
14+
"test"
15+
}
16+
17+
struct Foo;
18+
19+
impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
20+
fn get_lints(&self) -> LintArray {
21+
lint_array!(TEST_LINT)
22+
}
23+
24+
fn name(&self) -> &'static str {
25+
"Foo"
26+
}
27+
}
28+
29+
struct Bar;
30+
31+
impl_lint_pass!(Bar => [TEST_LINT]);
32+
33+
declare_lint_pass!(Baz => [TEST_LINT]);
34+
35+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: implementing `LintPass` by hand
2+
--> $DIR/lint_pass_impl_without_macro.rs:19:6
3+
|
4+
LL | impl LintPass for Foo {
5+
| ^^^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/lint_pass_impl_without_macro.rs:4:9
9+
|
10+
LL | #![deny(lint_pass_impl_without_macro)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)