]> git.lizzy.rs Git - rust.git/blob - src/librustc_lint/passes.rs
clean up error codes explanation
[rust.git] / src / librustc_lint / passes.rs
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>;