]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | use crate::context::{EarlyContext, LateContext}; |
2 | ||
3 | use rustc_data_structures::sync; | |
4 | use rustc_hir as hir; | |
5 | use rustc_session::lint::builtin::HardwiredLints; | |
6 | use rustc_session::lint::LintPass; | |
7 | use rustc_span::Span; | |
8 | use syntax::ast; | |
9 | ||
10 | #[macro_export] | |
11 | macro_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 | ||
84 | macro_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 | ||
90 | macro_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 | ||
98 | late_lint_methods!(declare_late_lint_pass, [], ['tcx]); | |
99 | ||
100 | impl LateLintPass<'_, '_> for HardwiredLints {} | |
101 | ||
102 | #[macro_export] | |
103 | macro_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] | |
110 | macro_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] | |
119 | macro_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] | |
154 | macro_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 | ||
214 | macro_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 | ||
220 | macro_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 | ||
228 | early_lint_methods!(declare_early_lint_pass, []); | |
229 | ||
230 | #[macro_export] | |
231 | macro_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] | |
238 | macro_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] | |
247 | macro_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. | |
282 | pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>; | |
283 | pub type LateLintPassObject = | |
284 | Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>; |