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