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