1 use crate::context::{EarlyContext, LateContext};
4 use rustc_data_structures::sync;
6 use rustc_session::lint::builtin::HardwiredLints;
7 use rustc_session::lint::LintPass;
8 use rustc_span::symbol::Ident;
12 macro_rules! late_lint_methods {
13 ($macro:path, $args:tt, [$hir:tt]) => (
14 $macro!($args, [$hir], [
15 fn check_body(a: &$hir hir::Body<$hir>);
16 fn check_body_post(a: &$hir hir::Body<$hir>);
18 fn check_crate_post();
19 fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
20 fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
21 fn check_item(a: &$hir hir::Item<$hir>);
22 fn check_item_post(a: &$hir hir::Item<$hir>);
23 fn check_local(a: &$hir hir::Local<$hir>);
24 fn check_block(a: &$hir hir::Block<$hir>);
25 fn check_block_post(a: &$hir hir::Block<$hir>);
26 fn check_stmt(a: &$hir hir::Stmt<$hir>);
27 fn check_arm(a: &$hir hir::Arm<$hir>);
28 fn check_pat(a: &$hir hir::Pat<$hir>);
29 fn check_expr(a: &$hir hir::Expr<$hir>);
30 fn check_expr_post(a: &$hir hir::Expr<$hir>);
31 fn check_ty(a: &$hir hir::Ty<$hir>);
32 fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
33 fn check_generics(a: &$hir hir::Generics<$hir>);
34 fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
36 a: rustc_hir::intravisit::FnKind<$hir>,
37 b: &$hir hir::FnDecl<$hir>,
38 c: &$hir hir::Body<$hir>,
41 fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
42 fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
43 fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
44 fn check_struct_def(a: &$hir hir::VariantData<$hir>);
45 fn check_field_def(a: &$hir hir::FieldDef<$hir>);
46 fn check_variant(a: &$hir hir::Variant<$hir>);
47 fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
48 fn check_attribute(a: &$hir 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: &$hir [ast::Attribute]);
54 /// Counterpart to `enter_lint_attrs`.
55 fn exit_lint_attrs(a: &$hir [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! expand_lint_pass_methods {
70 ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
71 $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
75 macro_rules! declare_late_lint_pass {
76 ([], [$hir:tt], [$($methods:tt)*]) => (
77 pub trait LateLintPass<$hir>: LintPass {
78 expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]);
83 late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
85 impl LateLintPass<'_> for HardwiredLints {}
88 macro_rules! expand_combined_late_lint_pass_method {
89 ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
90 $($self.$passes.$name $params;)*
95 macro_rules! expand_combined_late_lint_pass_methods {
96 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
97 $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
98 expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
104 macro_rules! declare_combined_late_lint_pass {
105 ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
106 #[allow(non_snake_case)]
108 $($passes: $passes,)*
112 $v fn new() -> Self {
114 $($passes: $constructor,)*
118 $v fn get_lints() -> LintArray {
119 let mut lints = Vec::new();
120 $(lints.extend_from_slice(&$passes::get_lints());)*
125 impl<'tcx> LateLintPass<'tcx> for $name {
126 expand_combined_late_lint_pass_methods!([$($passes),*], $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 b: &ast::TraitBoundModifier);
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, b: ast::NodeId);
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]);
179 macro_rules! expand_early_lint_pass_methods {
180 ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
181 $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
185 macro_rules! declare_early_lint_pass {
186 ([], [$($methods:tt)*]) => (
187 pub trait EarlyLintPass: LintPass {
188 expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
193 early_lint_methods!(declare_early_lint_pass, []);
196 macro_rules! expand_combined_early_lint_pass_method {
197 ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
198 $($self.$passes.$name $params;)*
203 macro_rules! expand_combined_early_lint_pass_methods {
204 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
205 $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
206 expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
212 macro_rules! declare_combined_early_lint_pass {
213 ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
214 #[allow(non_snake_case)]
216 $($passes: $passes,)*
220 $v fn new() -> Self {
222 $($passes: $constructor,)*
226 $v fn get_lints() -> LintArray {
227 let mut lints = Vec::new();
228 $(lints.extend_from_slice(&$passes::get_lints());)*
233 impl EarlyLintPass for $name {
234 expand_combined_early_lint_pass_methods!([$($passes),*], $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 + sync::Send + sync::Sync + 'static>;
248 pub type LateLintPassObject =
249 Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + sync::Sync + 'static>;