1 use crate::context::{EarlyContext, LateContext}; 2 3 use rustc_ast as ast; 4 use rustc_hir as hir; 5 use rustc_session::lint::builtin::HardwiredLints; 6 use rustc_session::lint::LintPass; 7 use rustc_span::def_id::LocalDefId; 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) => ( 14 $macro!($args, [ 15 fn check_body(a: &'tcx hir::Body<'tcx>); 16 fn check_body_post(a: &'tcx hir::Body<'tcx>); 17 fn check_crate(); 18 fn check_crate_post(); 19 fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId); 20 fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>); 21 fn check_item(a: &'tcx hir::Item<'tcx>); 22 fn check_item_post(a: &'tcx hir::Item<'tcx>); 23 fn check_local(a: &'tcx hir::Local<'tcx>); 24 fn check_block(a: &'tcx hir::Block<'tcx>); 25 fn check_block_post(a: &'tcx hir::Block<'tcx>); 26 fn check_stmt(a: &'tcx hir::Stmt<'tcx>); 27 fn check_arm(a: &'tcx hir::Arm<'tcx>); 28 fn check_pat(a: &'tcx hir::Pat<'tcx>); 29 fn check_expr(a: &'tcx hir::Expr<'tcx>); 30 fn check_expr_post(a: &'tcx hir::Expr<'tcx>); 31 fn check_ty(a: &'tcx hir::Ty<'tcx>); 32 fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>); 33 fn check_generics(a: &'tcx hir::Generics<'tcx>); 34 fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>); 35 fn check_fn( 36 a: rustc_hir::intravisit::FnKind<'tcx>, 37 b: &'tcx hir::FnDecl<'tcx>, 38 c: &'tcx hir::Body<'tcx>, 39 d: Span, 40 e: LocalDefId); 41 fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>); 42 fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>); 43 fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>); 44 fn check_struct_def(a: &'tcx hir::VariantData<'tcx>); 45 fn check_field_def(a: &'tcx hir::FieldDef<'tcx>); 46 fn check_variant(a: &'tcx hir::Variant<'tcx>); 47 fn check_path(a: &hir::Path<'tcx>, b: hir::HirId); 48 fn check_attribute(a: &'tcx 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: &'tcx [ast::Attribute]); 53 54 /// Counterpart to `enter_lint_attrs`. 55 fn exit_lint_attrs(a: &'tcx [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! declare_late_lint_pass { 70 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( 71 pub trait LateLintPass<'tcx>: LintPass { 72 $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})* 73 } 74 ) 75 } 76 77 // Declare the `LateLintPass` trait, which contains empty default definitions 78 // for all the `check_*` methods. 79 late_lint_methods!(declare_late_lint_pass, []); 80 81 impl LateLintPass<'_> for HardwiredLints {} 82 83 #[macro_export] 84 macro_rules! expand_combined_late_lint_pass_method { 85 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({ 86 $($self.$pass.$name $params;)* 87 }) 88 } 89 90 #[macro_export] 91 macro_rules! expand_combined_late_lint_pass_methods { 92 ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( 93 $(fn $name(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) { 94 expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); 95 })* 96 ) 97 } 98 99 /// Combines multiple lints passes into a single lint pass, at compile time, 100 /// for maximum speed. Each `check_foo` method in `$methods` within this pass 101 /// simply calls `check_foo` once per `$pass`. Compare with 102 /// `LateLintPassObjects`, which is similar, but combines lint passes at 103 /// runtime. 104 #[macro_export] 105 macro_rules! declare_combined_late_lint_pass { 106 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( 107 #[allow(non_snake_case)] 108 $v struct $name { 109 $($pass: $pass,)* 110 } 111 112 impl $name { 113 $v fn new() -> Self { 114 Self { 115 $($pass: $constructor,)* 116 } 117 } 118 119 $v fn get_lints() -> LintArray { 120 let mut lints = Vec::new(); 121 $(lints.extend_from_slice(&$pass::get_lints());)* 122 lints 123 } 124 } 125 126 impl<'tcx> LateLintPass<'tcx> for $name { 127 expand_combined_late_lint_pass_methods!([$($pass),*], $methods); 128 } 129 130 #[allow(rustc::lint_pass_impl_without_macro)] 131 impl LintPass for $name { 132 fn name(&self) -> &'static str { 133 panic!() 134 } 135 } 136 ) 137 } 138 139 #[macro_export] 140 macro_rules! early_lint_methods { 141 ($macro:path, $args:tt) => ( 142 $macro!($args, [ 143 fn check_param(a: &ast::Param); 144 fn check_ident(a: Ident); 145 fn check_crate(a: &ast::Crate); 146 fn check_crate_post(a: &ast::Crate); 147 fn check_item(a: &ast::Item); 148 fn check_item_post(a: &ast::Item); 149 fn check_local(a: &ast::Local); 150 fn check_block(a: &ast::Block); 151 fn check_stmt(a: &ast::Stmt); 152 fn check_arm(a: &ast::Arm); 153 fn check_pat(a: &ast::Pat); 154 fn check_pat_post(a: &ast::Pat); 155 fn check_expr(a: &ast::Expr); 156 fn check_ty(a: &ast::Ty); 157 fn check_generic_arg(a: &ast::GenericArg); 158 fn check_generic_param(a: &ast::GenericParam); 159 fn check_generics(a: &ast::Generics); 160 fn check_poly_trait_ref(a: &ast::PolyTraitRef); 161 fn check_fn(a: rustc_ast::visit::FnKind<'_>, c: Span, d_: ast::NodeId); 162 fn check_trait_item(a: &ast::AssocItem); 163 fn check_impl_item(a: &ast::AssocItem); 164 fn check_variant(a: &ast::Variant); 165 fn check_attribute(a: &ast::Attribute); 166 fn check_mac_def(a: &ast::MacroDef); 167 fn check_mac(a: &ast::MacCall); 168 169 /// Called when entering a syntax node that can have lint attributes such 170 /// as `#[allow(...)]`. Called with *all* the attributes of that node. 171 fn enter_lint_attrs(a: &[ast::Attribute]); 172 173 /// Counterpart to `enter_lint_attrs`. 174 fn exit_lint_attrs(a: &[ast::Attribute]); 175 176 fn enter_where_predicate(a: &ast::WherePredicate); 177 fn exit_where_predicate(a: &ast::WherePredicate); 178 ]); 179 ) 180 } 181 182 macro_rules! declare_early_lint_pass { 183 ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( 184 pub trait EarlyLintPass: LintPass { 185 $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})* 186 } 187 ) 188 } 189 190 // Declare the `EarlyLintPass` trait, which contains empty default definitions 191 // for all the `check_*` methods. 192 early_lint_methods!(declare_early_lint_pass, []); 193 194 #[macro_export] 195 macro_rules! expand_combined_early_lint_pass_method { 196 ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({ 197 $($self.$pass.$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 /// Combines multiple lints passes into a single lint pass, at compile time, 211 /// for maximum speed. Each `check_foo` method in `$methods` within this pass 212 /// simply calls `check_foo` once per `$pass`. Compare with 213 /// `EarlyLintPassObjects`, which is similar, but combines lint passes at 214 /// runtime. 215 #[macro_export] 216 macro_rules! declare_combined_early_lint_pass { 217 ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( 218 #[allow(non_snake_case)] 219 $v struct $name { 220 $($pass: $pass,)* 221 } 222 223 impl $name { 224 $v fn new() -> Self { 225 Self { 226 $($pass: $constructor,)* 227 } 228 } 229 230 $v fn get_lints() -> LintArray { 231 let mut lints = Vec::new(); 232 $(lints.extend_from_slice(&$pass::get_lints());)* 233 lints 234 } 235 } 236 237 impl EarlyLintPass for $name { 238 expand_combined_early_lint_pass_methods!([$($pass),*], $methods); 239 } 240 241 #[allow(rustc::lint_pass_impl_without_macro)] 242 impl LintPass for $name { 243 fn name(&self) -> &'static str { 244 panic!() 245 } 246 } 247 ) 248 } 249 250 /// A lint pass boxed up as a trait object. 251 pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>; 252 pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + 'tcx>; 253