-
Notifications
You must be signed in to change notification settings - Fork 14k
Description
The check_attr visitor here is missing several methods:
rust/compiler/rustc_passes/src/check_attr.rs
Lines 866 to 936 in e261649
| impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { | |
| type Map = Map<'tcx>; | |
| fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { | |
| NestedVisitorMap::OnlyBodies(self.tcx.hir()) | |
| } | |
| fn visit_item(&mut self, item: &'tcx Item<'tcx>) { | |
| let target = Target::from_item(item); | |
| self.check_attributes( | |
| item.hir_id, | |
| item.attrs, | |
| &item.span, | |
| target, | |
| Some(ItemLike::Item(item)), | |
| ); | |
| intravisit::walk_item(self, item) | |
| } | |
| fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) { | |
| let target = Target::from_trait_item(trait_item); | |
| self.check_attributes(trait_item.hir_id, &trait_item.attrs, &trait_item.span, target, None); | |
| intravisit::walk_trait_item(self, trait_item) | |
| } | |
| fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) { | |
| let target = Target::from_foreign_item(f_item); | |
| self.check_attributes( | |
| f_item.hir_id, | |
| &f_item.attrs, | |
| &f_item.span, | |
| target, | |
| Some(ItemLike::ForeignItem(f_item)), | |
| ); | |
| intravisit::walk_foreign_item(self, f_item) | |
| } | |
| fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { | |
| let target = target_from_impl_item(self.tcx, impl_item); | |
| self.check_attributes(impl_item.hir_id, &impl_item.attrs, &impl_item.span, target, None); | |
| intravisit::walk_impl_item(self, impl_item) | |
| } | |
| fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { | |
| // When checking statements ignore expressions, they will be checked later. | |
| if let hir::StmtKind::Local(ref l) = stmt.kind { | |
| self.check_attributes(l.hir_id, &l.attrs, &stmt.span, Target::Statement, None); | |
| } | |
| intravisit::walk_stmt(self, stmt) | |
| } | |
| fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { | |
| let target = match expr.kind { | |
| hir::ExprKind::Closure(..) => Target::Closure, | |
| _ => Target::Expression, | |
| }; | |
| self.check_attributes(expr.hir_id, &expr.attrs, &expr.span, target, None); | |
| intravisit::walk_expr(self, expr) | |
| } | |
| fn visit_variant( | |
| &mut self, | |
| variant: &'tcx hir::Variant<'tcx>, | |
| generics: &'tcx hir::Generics<'tcx>, | |
| item_id: HirId, | |
| ) { | |
| self.check_attributes(variant.id, variant.attrs, &variant.span, Target::Variant, None); | |
| intravisit::walk_variant(self, variant, generics, item_id) | |
| } | |
| } |
A quick search (for attrs:) in the HIR definition finds these additional types that can contain attributes (they're also missing from the hir::Target enum, which should probably be renamed to AttrTarget but that's besides the point):
(click to see definition code snippets)
(summary: GenericParam, MacroDef, Arm, Param, StructField)
GenericParam, MacroDef, Arm, Param, StructField)GenericParamrust/compiler/rustc_hir/src/hir.rs
Lines 425 to 428 in e261649
pub struct GenericParam<'hir> { pub hir_id: HirId, pub name: ParamName, pub attrs: &'hir [Attribute], MacroDef(is this handled elsewhere?)rust/compiler/rustc_hir/src/hir.rs
Lines 722 to 725 in e261649
pub struct MacroDef<'hir> { pub ident: Ident, pub vis: Visibility<'hir>, pub attrs: &'hir [Attribute], Armrust/compiler/rustc_hir/src/hir.rs
Lines 1147 to 1151 in e261649
pub struct Arm<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, pub span: Span, pub attrs: &'hir [Attribute], Paramrust/compiler/rustc_hir/src/hir.rs
Lines 2183 to 2184 in e261649
pub struct Param<'hir> { pub attrs: &'hir [Attribute], StructFieldrust/compiler/rustc_hir/src/hir.rs
Lines 2390 to 2397 in e261649
pub struct StructField<'hir> { pub span: Span, #[stable_hasher(project(name))] pub ident: Ident, pub vis: Visibility<'hir>, pub hir_id: HirId, pub ty: &'hir Ty<'hir>, pub attrs: &'hir [Attribute],
This isn't necessary a bug for some of them, as there is special validation elsewhere, e.g.:
rust/compiler/rustc_ast_passes/src/ast_validation.rs
Lines 377 to 378 in e261649
| "allow, cfg, cfg_attr, deny, \ | |
| forbid, and warn are the only allowed built-in attributes in function parameters", |
But it's not as uniform and future-proof as it could be. It might even be worth having a contextual attribute Target, and handling all attributes on visit_attr, or a hybrid solution that ICEs when visit_attr comes across an attribute not already handled.
And I did end up finding at least one bug, this compiles without any warnings (try on playground):
fn main() {
match 5 {
#[inline] _ => {}
}
}