1 use crate::context::{EarlyContext, LateContext};
5 use rustc_session::lint::builtin::HardwiredLints;
6 use rustc_session::lint::LintPass;
7 use rustc_span::symbol::Ident;
11 macro_rules! late_lint_methods {
12 ($macro:path, $args:tt) => (
14 fn check_body(a: &'tcx hir::Body<'tcx>);
15 fn check_body_post(a: &'tcx hir::Body<'tcx>);
17 fn check_crate_post();
18 fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId);
19 fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>);
20 fn check_item(a: &'tcx hir::Item<'tcx>);
21 fn check_item_post(a: &'tcx hir::Item<'tcx>);
22 fn check_local(a: &'tcx hir::Local<'tcx>);
23 fn check_block(a: &'tcx hir::Block<'tcx>);
24 fn check_block_post(a: &'tcx hir::Block<'tcx>);
25 fn check_stmt(a: &'tcx hir::Stmt<'tcx>);
26 fn check_arm(a: &'tcx hir::Arm<'tcx>);
27 fn check_pat(a: &'tcx hir::Pat<'tcx>);
28 fn check_expr(a: &'tcx hir::Expr<'tcx>);
29 fn check_expr_post(a: &'tcx hir::Expr<'tcx>);
30 fn check_ty(a: &'tcx hir::Ty<'tcx>);
31 fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>);
32 fn check_generics(a: &'tcx hir::Generics<'tcx>);
33 fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>);
35 a: rustc_hir::intravisit::FnKind<'tcx>,
36 b: &'tcx hir::FnDecl<'tcx>,
37 c: &'tcx hir::Body<'tcx>,
40 fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
41 fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
42 fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
43 fn check_struct_def(a: &'tcx hir::VariantData<'tcx>);
44 fn check_field_def(a: &'tcx hir::FieldDef<'tcx>);
45 fn check_variant(a: &'tcx hir::Variant<'tcx>);
46 fn check_path(a: &hir::Path<'tcx>, b: hir::HirId);
47 fn check_attribute(a: &'tcx ast::Attribute);
49 /// Called when entering a syntax node that can have lint attributes such
50 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
51 fn enter_lint_attrs(a: &'tcx [ast::Attribute]);
53 /// Counterpart to `enter_lint_attrs`.
54 fn exit_lint_attrs(a: &'tcx [ast::Attribute]);
59 /// Trait for types providing lint checks.
61 /// Each `check` method checks a single syntax node, and should not
62 /// invoke methods recursively (unlike `Visitor`). By default they
65 // FIXME: eliminate the duplication with `Visitor`. But this also
66 // contains a few lint-specific methods with no equivalent in `Visitor`.
68 macro_rules! declare_late_lint_pass {
69 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
70 pub trait LateLintPass<'tcx>: LintPass {
71 $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})*
76 // Declare the `LateLintPass` trait, which contains empty default definitions
77 // for all the `check_*` methods.
78 late_lint_methods!(declare_late_lint_pass, []);
80 impl LateLintPass<'_> for HardwiredLints {}
83 macro_rules! expand_combined_late_lint_pass_method {
84 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
85 $($self.$pass.$name $params;)*
90 macro_rules! expand_combined_late_lint_pass_methods {
91 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
92 $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
93 expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
98 /// Combines multiple lints passes into a single lint pass, at compile time,
99 /// for maximum speed. Each `check_foo` method in `$methods` within this pass
100 /// simply calls `check_foo` once per `$pass`. Compare with
101 /// `LateLintPassObjects`, which is similar, but combines lint passes at
104 macro_rules! declare_combined_late_lint_pass {
105 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
106 #[allow(non_snake_case)]
112 $v fn new() -> Self {
114 $($pass: $constructor,)*
118 $v fn get_lints() -> LintArray {
119 let mut lints = Vec::new();
120 $(lints.extend_from_slice(&$pass::get_lints());)*
125 impl<'tcx> LateLintPass<'tcx> for $name {
126 expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
129 #[allow(rustc::lint_pass_impl_without_macro)]
130 impl LintPass for $name {
131 fn name(&self) -> &'static str {
139 macro_rules! early_lint_methods {
140 ($macro:path, $args:tt) => (
142 fn check_param(a: &ast::Param);
143 fn check_ident(a: Ident);
144 fn check_crate(a: &ast::Crate);
145 fn check_crate_post(a: &ast::Crate);
146 fn check_item(a: &ast::Item);
147 fn check_item_post(a: &ast::Item);
148 fn check_local(a: &ast::Local);
149 fn check_block(a: &ast::Block);
150 fn check_stmt(a: &ast::Stmt);
151 fn check_arm(a: &ast::Arm);
152 fn check_pat(a: &ast::Pat);
153 fn check_pat_post(a: &ast::Pat);
154 fn check_expr(a: &ast::Expr);
155 fn check_ty(a: &ast::Ty);
156 fn check_generic_arg(a: &ast::GenericArg);
157 fn check_generic_param(a: &ast::GenericParam);
158 fn check_generics(a: &ast::Generics);
159 fn check_poly_trait_ref(a: &ast::PolyTraitRef);
160 fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId);
161 fn check_trait_item(a: &ast::AssocItem);
162 fn check_impl_item(a: &ast::AssocItem);
163 fn check_variant(a: &ast::Variant);
164 fn check_attribute(a: &ast::Attribute);
165 fn check_mac_def(a: &ast::MacroDef);
166 fn check_mac(a: &ast::MacCall);
168 /// Called when entering a syntax node that can have lint attributes such
169 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
170 fn enter_lint_attrs(a: &[ast::Attribute]);
172 /// Counterpart to `enter_lint_attrs`.
173 fn exit_lint_attrs(a: &[ast::Attribute]);
178 macro_rules! declare_early_lint_pass {
179 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
180 pub trait EarlyLintPass: LintPass {
181 $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})*
186 // Declare the `EarlyLintPass` trait, which contains empty default definitions
187 // for all the `check_*` methods.
188 early_lint_methods!(declare_early_lint_pass, []);
191 macro_rules! expand_combined_early_lint_pass_method {
192 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
193 $($self.$pass.$name $params;)*
198 macro_rules! expand_combined_early_lint_pass_methods {
199 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
200 $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
201 expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
206 /// Combines multiple lints passes into a single lint pass, at compile time,
207 /// for maximum speed. Each `check_foo` method in `$methods` within this pass
208 /// simply calls `check_foo` once per `$pass`. Compare with
209 /// `EarlyLintPassObjects`, which is similar, but combines lint passes at
212 macro_rules! declare_combined_early_lint_pass {
213 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
214 #[allow(non_snake_case)]
220 $v fn new() -> Self {
222 $($pass: $constructor,)*
226 $v fn get_lints() -> LintArray {
227 let mut lints = Vec::new();
228 $(lints.extend_from_slice(&$pass::get_lints());)*
233 impl EarlyLintPass for $name {
234 expand_combined_early_lint_pass_methods!([$($pass),*], $methods);
237 #[allow(rustc::lint_pass_impl_without_macro)]
238 impl LintPass for $name {
239 fn name(&self) -> &'static str {
246 /// A lint pass boxed up as a trait object.
247 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
248 pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>;