1 use crate::context::{EarlyContext, LateContext};
5 use rustc_session::lint::builtin::HardwiredLints;
6 use rustc_session::lint::LintPass;
7 use rustc_span::def_id::LocalDefId;
8 use rustc_span::symbol::Ident;
12 macro_rules! late_lint_methods {
13 ($macro:path, $args:tt) => (
15 fn check_body(a: &'tcx hir::Body<'tcx>);
16 fn check_body_post(a: &'tcx hir::Body<'tcx>);
18 fn check_crate_post();
19 fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId);
20 fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>);
21 fn check_item(a: &'tcx hir::Item<'tcx>);
22 fn check_item_post(a: &'tcx hir::Item<'tcx>);
23 fn check_local(a: &'tcx hir::Local<'tcx>);
24 fn check_block(a: &'tcx hir::Block<'tcx>);
25 fn check_block_post(a: &'tcx hir::Block<'tcx>);
26 fn check_stmt(a: &'tcx hir::Stmt<'tcx>);
27 fn check_arm(a: &'tcx hir::Arm<'tcx>);
28 fn check_pat(a: &'tcx hir::Pat<'tcx>);
29 fn check_expr(a: &'tcx hir::Expr<'tcx>);
30 fn check_expr_post(a: &'tcx hir::Expr<'tcx>);
31 fn check_ty(a: &'tcx hir::Ty<'tcx>);
32 fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>);
33 fn check_generics(a: &'tcx hir::Generics<'tcx>);
34 fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>);
36 a: rustc_hir::intravisit::FnKind<'tcx>,
37 b: &'tcx hir::FnDecl<'tcx>,
38 c: &'tcx hir::Body<'tcx>,
41 fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
42 fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
43 fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
44 fn check_struct_def(a: &'tcx hir::VariantData<'tcx>);
45 fn check_field_def(a: &'tcx hir::FieldDef<'tcx>);
46 fn check_variant(a: &'tcx hir::Variant<'tcx>);
47 fn check_path(a: &hir::Path<'tcx>, b: hir::HirId);
48 fn check_attribute(a: &'tcx ast::Attribute);
50 /// Called when entering a syntax node that can have lint attributes such
51 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
52 fn enter_lint_attrs(a: &'tcx [ast::Attribute]);
54 /// Counterpart to `enter_lint_attrs`.
55 fn exit_lint_attrs(a: &'tcx [ast::Attribute]);
60 /// Trait for types providing lint checks.
62 /// Each `check` method checks a single syntax node, and should not
63 /// invoke methods recursively (unlike `Visitor`). By default they
66 // FIXME: eliminate the duplication with `Visitor`. But this also
67 // contains a few lint-specific methods with no equivalent in `Visitor`.
69 macro_rules! declare_late_lint_pass {
70 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
71 pub trait LateLintPass<'tcx>: LintPass {
72 $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})*
77 // Declare the `LateLintPass` trait, which contains empty default definitions
78 // for all the `check_*` methods.
79 late_lint_methods!(declare_late_lint_pass, []);
81 impl LateLintPass<'_> for HardwiredLints {}
84 macro_rules! expand_combined_late_lint_pass_method {
85 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
86 $($self.$pass.$name $params;)*
91 macro_rules! expand_combined_late_lint_pass_methods {
92 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
93 $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
94 expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
99 /// Combines multiple lints passes into a single lint pass, at compile time,
100 /// for maximum speed. Each `check_foo` method in `$methods` within this pass
101 /// simply calls `check_foo` once per `$pass`. Compare with
102 /// `LateLintPassObjects`, which is similar, but combines lint passes at
105 macro_rules! declare_combined_late_lint_pass {
106 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
107 #[allow(non_snake_case)]
113 $v fn new() -> Self {
115 $($pass: $constructor,)*
119 $v fn get_lints() -> LintArray {
120 let mut lints = Vec::new();
121 $(lints.extend_from_slice(&$pass::get_lints());)*
126 impl<'tcx> LateLintPass<'tcx> for $name {
127 expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
130 #[allow(rustc::lint_pass_impl_without_macro)]
131 impl LintPass for $name {
132 fn name(&self) -> &'static str {
140 macro_rules! early_lint_methods {
141 ($macro:path, $args:tt) => (
143 fn check_param(a: &ast::Param);
144 fn check_ident(a: Ident);
145 fn check_crate(a: &ast::Crate);
146 fn check_crate_post(a: &ast::Crate);
147 fn check_item(a: &ast::Item);
148 fn check_item_post(a: &ast::Item);
149 fn check_local(a: &ast::Local);
150 fn check_block(a: &ast::Block);
151 fn check_stmt(a: &ast::Stmt);
152 fn check_arm(a: &ast::Arm);
153 fn check_pat(a: &ast::Pat);
154 fn check_pat_post(a: &ast::Pat);
155 fn check_expr(a: &ast::Expr);
156 fn check_ty(a: &ast::Ty);
157 fn check_generic_arg(a: &ast::GenericArg);
158 fn check_generic_param(a: &ast::GenericParam);
159 fn check_generics(a: &ast::Generics);
160 fn check_poly_trait_ref(a: &ast::PolyTraitRef);
161 fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId);
162 fn check_trait_item(a: &ast::AssocItem);
163 fn check_impl_item(a: &ast::AssocItem);
164 fn check_variant(a: &ast::Variant);
165 fn check_attribute(a: &ast::Attribute);
166 fn check_mac_def(a: &ast::MacroDef);
167 fn check_mac(a: &ast::MacCall);
169 /// Called when entering a syntax node that can have lint attributes such
170 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
171 fn enter_lint_attrs(a: &[ast::Attribute]);
173 /// Counterpart to `enter_lint_attrs`.
174 fn exit_lint_attrs(a: &[ast::Attribute]);
176 fn enter_where_predicate(a: &ast::WherePredicate);
177 fn exit_where_predicate(a: &ast::WherePredicate);
182 macro_rules! declare_early_lint_pass {
183 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
184 pub trait EarlyLintPass: LintPass {
185 $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})*
190 // Declare the `EarlyLintPass` trait, which contains empty default definitions
191 // for all the `check_*` methods.
192 early_lint_methods!(declare_early_lint_pass, []);
195 macro_rules! expand_combined_early_lint_pass_method {
196 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
197 $($self.$pass.$name $params;)*
202 macro_rules! expand_combined_early_lint_pass_methods {
203 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
204 $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
205 expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
210 /// Combines multiple lints passes into a single lint pass, at compile time,
211 /// for maximum speed. Each `check_foo` method in `$methods` within this pass
212 /// simply calls `check_foo` once per `$pass`. Compare with
213 /// `EarlyLintPassObjects`, which is similar, but combines lint passes at
216 macro_rules! declare_combined_early_lint_pass {
217 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
218 #[allow(non_snake_case)]
224 $v fn new() -> Self {
226 $($pass: $constructor,)*
230 $v fn get_lints() -> LintArray {
231 let mut lints = Vec::new();
232 $(lints.extend_from_slice(&$pass::get_lints());)*
237 impl EarlyLintPass for $name {
238 expand_combined_early_lint_pass_methods!([$($pass),*], $methods);
241 #[allow(rustc::lint_pass_impl_without_macro)]
242 impl LintPass for $name {
243 fn name(&self) -> &'static str {
250 /// A lint pass boxed up as a trait object.
251 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
252 pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>;