]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/passes.rs
Rollup merge of #80159 - jyn514:array, r=m-ou-se
[rust.git] / compiler / rustc_lint / src / passes.rs
1 use crate::context::{EarlyContext, LateContext};
2
3 use rustc_ast as ast;
4 use rustc_data_structures::sync;
5 use rustc_hir as hir;
6 use rustc_session::lint::builtin::HardwiredLints;
7 use rustc_session::lint::LintPass;
8 use rustc_span::symbol::{Ident, Symbol};
9 use rustc_span::Span;
10
11 #[macro_export]
12 macro_rules! late_lint_methods {
13     ($macro:path, $args:tt, [$hir:tt]) => (
14         $macro!($args, [$hir], [
15             fn check_param(a: &$hir hir::Param<$hir>);
16             fn check_body(a: &$hir hir::Body<$hir>);
17             fn check_body_post(a: &$hir hir::Body<$hir>);
18             fn check_name(a: Span, b: Symbol);
19             fn check_crate(a: &$hir hir::Crate<$hir>);
20             fn check_crate_post(a: &$hir hir::Crate<$hir>);
21             fn check_mod(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
22             fn check_mod_post(a: &$hir hir::Mod<$hir>, b: Span, c: hir::HirId);
23             fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
24             fn check_foreign_item_post(a: &$hir hir::ForeignItem<$hir>);
25             fn check_item(a: &$hir hir::Item<$hir>);
26             fn check_item_post(a: &$hir hir::Item<$hir>);
27             fn check_local(a: &$hir hir::Local<$hir>);
28             fn check_block(a: &$hir hir::Block<$hir>);
29             fn check_block_post(a: &$hir hir::Block<$hir>);
30             fn check_stmt(a: &$hir hir::Stmt<$hir>);
31             fn check_arm(a: &$hir hir::Arm<$hir>);
32             fn check_pat(a: &$hir hir::Pat<$hir>);
33             fn check_expr(a: &$hir hir::Expr<$hir>);
34             fn check_expr_post(a: &$hir hir::Expr<$hir>);
35             fn check_ty(a: &$hir hir::Ty<$hir>);
36             fn check_generic_arg(a: &$hir hir::GenericArg<$hir>);
37             fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
38             fn check_generics(a: &$hir hir::Generics<$hir>);
39             fn check_where_predicate(a: &$hir hir::WherePredicate<$hir>);
40             fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>, b: hir::TraitBoundModifier);
41             fn check_fn(
42                 a: rustc_hir::intravisit::FnKind<$hir>,
43                 b: &$hir hir::FnDecl<$hir>,
44                 c: &$hir hir::Body<$hir>,
45                 d: Span,
46                 e: hir::HirId);
47             fn check_fn_post(
48                 a: rustc_hir::intravisit::FnKind<$hir>,
49                 b: &$hir hir::FnDecl<$hir>,
50                 c: &$hir hir::Body<$hir>,
51                 d: Span,
52                 e: hir::HirId
53             );
54             fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
55             fn check_trait_item_post(a: &$hir hir::TraitItem<$hir>);
56             fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
57             fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
58             fn check_struct_def(a: &$hir hir::VariantData<$hir>);
59             fn check_struct_def_post(a: &$hir hir::VariantData<$hir>);
60             fn check_struct_field(a: &$hir hir::StructField<$hir>);
61             fn check_variant(a: &$hir hir::Variant<$hir>);
62             fn check_variant_post(a: &$hir hir::Variant<$hir>);
63             fn check_lifetime(a: &$hir hir::Lifetime);
64             fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
65             fn check_attribute(a: &$hir ast::Attribute);
66
67             /// Called when entering a syntax node that can have lint attributes such
68             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
69             fn enter_lint_attrs(a: &$hir [ast::Attribute]);
70
71             /// Counterpart to `enter_lint_attrs`.
72             fn exit_lint_attrs(a: &$hir [ast::Attribute]);
73         ]);
74     )
75 }
76
77 /// Trait for types providing lint checks.
78 ///
79 /// Each `check` method checks a single syntax node, and should not
80 /// invoke methods recursively (unlike `Visitor`). By default they
81 /// do nothing.
82 //
83 // FIXME: eliminate the duplication with `Visitor`. But this also
84 // contains a few lint-specific methods with no equivalent in `Visitor`.
85
86 macro_rules! expand_lint_pass_methods {
87     ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
88         $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
89     )
90 }
91
92 macro_rules! declare_late_lint_pass {
93     ([], [$hir:tt], [$($methods:tt)*]) => (
94         pub trait LateLintPass<$hir>: LintPass {
95             expand_lint_pass_methods!(&LateContext<$hir>, [$($methods)*]);
96         }
97     )
98 }
99
100 late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
101
102 impl LateLintPass<'_> for HardwiredLints {}
103
104 #[macro_export]
105 macro_rules! expand_combined_late_lint_pass_method {
106     ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
107         $($self.$passes.$name $params;)*
108     })
109 }
110
111 #[macro_export]
112 macro_rules! expand_combined_late_lint_pass_methods {
113     ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
114         $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) {
115             expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
116         })*
117     )
118 }
119
120 #[macro_export]
121 macro_rules! declare_combined_late_lint_pass {
122     ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
123         #[allow(non_snake_case)]
124         $v struct $name {
125             $($passes: $passes,)*
126         }
127
128         impl $name {
129             $v fn new() -> Self {
130                 Self {
131                     $($passes: $constructor,)*
132                 }
133             }
134
135             $v fn get_lints() -> LintArray {
136                 let mut lints = Vec::new();
137                 $(lints.extend_from_slice(&$passes::get_lints());)*
138                 lints
139             }
140         }
141
142         impl<'tcx> LateLintPass<'tcx> for $name {
143             expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
144         }
145
146         #[allow(rustc::lint_pass_impl_without_macro)]
147         impl LintPass for $name {
148             fn name(&self) -> &'static str {
149                 panic!()
150             }
151         }
152     )
153 }
154
155 #[macro_export]
156 macro_rules! early_lint_methods {
157     ($macro:path, $args:tt) => (
158         $macro!($args, [
159             fn check_param(a: &ast::Param);
160             fn check_ident(a: Ident);
161             fn check_crate(a: &ast::Crate);
162             fn check_crate_post(a: &ast::Crate);
163             fn check_mod(a: &ast::Mod, b: Span, c: ast::NodeId);
164             fn check_mod_post(a: &ast::Mod, b: Span, c: ast::NodeId);
165             fn check_foreign_item(a: &ast::ForeignItem);
166             fn check_foreign_item_post(a: &ast::ForeignItem);
167             fn check_item(a: &ast::Item);
168             fn check_item_post(a: &ast::Item);
169             fn check_local(a: &ast::Local);
170             fn check_block(a: &ast::Block);
171             fn check_block_post(a: &ast::Block);
172             fn check_stmt(a: &ast::Stmt);
173             fn check_arm(a: &ast::Arm);
174             fn check_pat(a: &ast::Pat);
175             fn check_anon_const(a: &ast::AnonConst);
176             fn check_pat_post(a: &ast::Pat);
177             fn check_expr(a: &ast::Expr);
178             fn check_expr_post(a: &ast::Expr);
179             fn check_ty(a: &ast::Ty);
180             fn check_generic_arg(a: &ast::GenericArg);
181             fn check_generic_param(a: &ast::GenericParam);
182             fn check_generics(a: &ast::Generics);
183             fn check_where_predicate(a: &ast::WherePredicate);
184             fn check_poly_trait_ref(a: &ast::PolyTraitRef,
185                                     b: &ast::TraitBoundModifier);
186             fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId);
187             fn check_fn_post(
188                 a: rustc_ast::visit::FnKind<'_>,
189                 c: Span,
190                 d: ast::NodeId
191             );
192             fn check_trait_item(a: &ast::AssocItem);
193             fn check_trait_item_post(a: &ast::AssocItem);
194             fn check_impl_item(a: &ast::AssocItem);
195             fn check_impl_item_post(a: &ast::AssocItem);
196             fn check_struct_def(a: &ast::VariantData);
197             fn check_struct_def_post(a: &ast::VariantData);
198             fn check_struct_field(a: &ast::StructField);
199             fn check_variant(a: &ast::Variant);
200             fn check_variant_post(a: &ast::Variant);
201             fn check_lifetime(a: &ast::Lifetime);
202             fn check_path(a: &ast::Path, b: ast::NodeId);
203             fn check_attribute(a: &ast::Attribute);
204             fn check_mac_def(a: &ast::MacroDef, b: ast::NodeId);
205             fn check_mac(a: &ast::MacCall);
206
207             /// Called when entering a syntax node that can have lint attributes such
208             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
209             fn enter_lint_attrs(a: &[ast::Attribute]);
210
211             /// Counterpart to `enter_lint_attrs`.
212             fn exit_lint_attrs(a: &[ast::Attribute]);
213         ]);
214     )
215 }
216
217 macro_rules! expand_early_lint_pass_methods {
218     ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
219         $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
220     )
221 }
222
223 macro_rules! declare_early_lint_pass {
224     ([], [$($methods:tt)*]) => (
225         pub trait EarlyLintPass: LintPass {
226             expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
227         }
228     )
229 }
230
231 early_lint_methods!(declare_early_lint_pass, []);
232
233 #[macro_export]
234 macro_rules! expand_combined_early_lint_pass_method {
235     ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
236         $($self.$passes.$name $params;)*
237     })
238 }
239
240 #[macro_export]
241 macro_rules! expand_combined_early_lint_pass_methods {
242     ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
243         $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) {
244             expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*));
245         })*
246     )
247 }
248
249 #[macro_export]
250 macro_rules! declare_combined_early_lint_pass {
251     ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
252         #[allow(non_snake_case)]
253         $v struct $name {
254             $($passes: $passes,)*
255         }
256
257         impl $name {
258             $v fn new() -> Self {
259                 Self {
260                     $($passes: $constructor,)*
261                 }
262             }
263
264             $v fn get_lints() -> LintArray {
265                 let mut lints = Vec::new();
266                 $(lints.extend_from_slice(&$passes::get_lints());)*
267                 lints
268             }
269         }
270
271         impl EarlyLintPass for $name {
272             expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
273         }
274
275         #[allow(rustc::lint_pass_impl_without_macro)]
276         impl LintPass for $name {
277             fn name(&self) -> &'static str {
278                 panic!()
279             }
280         }
281     )
282 }
283
284 /// A lint pass boxed up as a trait object.
285 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
286 pub type LateLintPassObject =
287     Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + sync::Sync + 'static>;