]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/passes.rs
Rollup merge of #104976 - WaffleLapkin:move_comments, r=cjgillot
[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;
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_body(a: &$hir hir::Body<$hir>);
16             fn check_body_post(a: &$hir hir::Body<$hir>);
17             fn check_crate();
18             fn check_crate_post();
19             fn check_mod(a: &$hir hir::Mod<$hir>, b: 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>);
35             fn check_fn(
36                 a: rustc_hir::intravisit::FnKind<$hir>,
37                 b: &$hir hir::FnDecl<$hir>,
38                 c: &$hir hir::Body<$hir>,
39                 d: Span,
40                 e: hir::HirId);
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);
49
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]);
53
54             /// Counterpart to `enter_lint_attrs`.
55             fn exit_lint_attrs(a: &$hir [ast::Attribute]);
56         ]);
57     )
58 }
59
60 /// Trait for types providing lint checks.
61 ///
62 /// Each `check` method checks a single syntax node, and should not
63 /// invoke methods recursively (unlike `Visitor`). By default they
64 /// do nothing.
65 //
66 // FIXME: eliminate the duplication with `Visitor`. But this also
67 // contains a few lint-specific methods with no equivalent in `Visitor`.
68
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),*) {})*
72     )
73 }
74
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)*]);
79         }
80     )
81 }
82
83 late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
84
85 impl LateLintPass<'_> for HardwiredLints {}
86
87 #[macro_export]
88 macro_rules! expand_combined_late_lint_pass_method {
89     ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
90         $($self.$passes.$name $params;)*
91     })
92 }
93
94 #[macro_export]
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),*));
99         })*
100     )
101 }
102
103 #[macro_export]
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)]
107         $v struct $name {
108             $($passes: $passes,)*
109         }
110
111         impl $name {
112             $v fn new() -> Self {
113                 Self {
114                     $($passes: $constructor,)*
115                 }
116             }
117
118             $v fn get_lints() -> LintArray {
119                 let mut lints = Vec::new();
120                 $(lints.extend_from_slice(&$passes::get_lints());)*
121                 lints
122             }
123         }
124
125         impl<'tcx> LateLintPass<'tcx> for $name {
126             expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
127         }
128
129         #[allow(rustc::lint_pass_impl_without_macro)]
130         impl LintPass for $name {
131             fn name(&self) -> &'static str {
132                 panic!()
133             }
134         }
135     )
136 }
137
138 #[macro_export]
139 macro_rules! early_lint_methods {
140     ($macro:path, $args:tt) => (
141         $macro!($args, [
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);
167
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]);
171
172             /// Counterpart to `enter_lint_attrs`.
173             fn exit_lint_attrs(a: &[ast::Attribute]);
174         ]);
175     )
176 }
177
178 macro_rules! expand_early_lint_pass_methods {
179     ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
180         $(#[inline(always)] fn $name(&mut self, _: $context, $(_: $arg),*) {})*
181     )
182 }
183
184 macro_rules! declare_early_lint_pass {
185     ([], [$($methods:tt)*]) => (
186         pub trait EarlyLintPass: LintPass {
187             expand_early_lint_pass_methods!(&EarlyContext<'_>, [$($methods)*]);
188         }
189     )
190 }
191
192 early_lint_methods!(declare_early_lint_pass, []);
193
194 #[macro_export]
195 macro_rules! expand_combined_early_lint_pass_method {
196     ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
197         $($self.$passes.$name $params;)*
198     })
199 }
200
201 #[macro_export]
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),*));
206         })*
207     )
208 }
209
210 #[macro_export]
211 macro_rules! declare_combined_early_lint_pass {
212     ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
213         #[allow(non_snake_case)]
214         $v struct $name {
215             $($passes: $passes,)*
216         }
217
218         impl $name {
219             $v fn new() -> Self {
220                 Self {
221                     $($passes: $constructor,)*
222                 }
223             }
224
225             $v fn get_lints() -> LintArray {
226                 let mut lints = Vec::new();
227                 $(lints.extend_from_slice(&$passes::get_lints());)*
228                 lints
229             }
230         }
231
232         impl EarlyLintPass for $name {
233             expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
234         }
235
236         #[allow(rustc::lint_pass_impl_without_macro)]
237         impl LintPass for $name {
238             fn name(&self) -> &'static str {
239                 panic!()
240             }
241         }
242     )
243 }
244
245 /// A lint pass boxed up as a trait object.
246 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>;
247 pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>;