1
Fork 0

Auto merge of #79519 - cjgillot:noattr, r=wesleywiser

Store HIR attributes in a side table

Same idea as #72015 but for attributes.
The objective is to reduce incr-comp invalidations due to modified attributes.
Notably, those due to modified doc comments.

Implementation:
- collect attributes during AST->HIR lowering, in `LocalDefId -> ItemLocalId -> &[Attributes]` nested tables;
- access the attributes through a `hir_owner_attrs` query;
- local refactorings to use this access;
- remove `attrs` from HIR data structures one-by-one.

Change in behaviour:
- the HIR visitor traverses all attributes at once instead of parent-by-parent;
- attribute arrays are sometimes duplicated: for statements and variant constructors;
- as a consequence, attributes are marked as used after unused-attribute lint emission to avoid duplicate lints.

~~Current bug: the lint level is not correctly applied in `std::backtrace_rs`, triggering an unused attribute warning on `#![no_std]`. I welcome suggestions.~~
This commit is contained in:
bors 2021-03-10 08:40:51 +00:00
commit dff1edf919
88 changed files with 936 additions and 920 deletions

View file

@ -258,9 +258,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
ex.span = e.span; ex.span = e.span;
} }
// Merge attributes into the inner expression. // Merge attributes into the inner expression.
let mut attrs: Vec<_> = e.attrs.iter().map(|a| self.lower_attr(a)).collect(); if !e.attrs.is_empty() {
attrs.extend::<Vec<_>>(ex.attrs.into()); let old_attrs = self.attrs.get(&ex.hir_id).map(|la| *la).unwrap_or(&[]);
ex.attrs = attrs.into(); self.attrs.insert(
ex.hir_id,
&*self.arena.alloc_from_iter(
e.attrs
.iter()
.map(|a| self.lower_attr(a))
.chain(old_attrs.iter().cloned()),
),
);
}
return ex; return ex;
} }
@ -272,12 +281,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
}; };
hir::Expr { let hir_id = self.lower_node_id(e.id);
hir_id: self.lower_node_id(e.id), self.lower_attrs(hir_id, &e.attrs);
kind, hir::Expr { hir_id, kind, span: e.span }
span: e.span,
attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
}
}) })
} }
@ -618,14 +624,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::Guard::If(self.lower_expr(cond)) hir::Guard::If(self.lower_expr(cond))
} }
}); });
hir::Arm { let hir_id = self.next_id();
hir_id: self.next_id(), self.lower_attrs(hir_id, &arm.attrs);
attrs: self.lower_attrs(&arm.attrs), hir::Arm { hir_id, pat, guard, body: self.lower_expr(&arm.body), span: arm.span }
pat,
guard,
body: self.lower_expr(&arm.body),
span: arm.span,
}
} }
/// Lower an `async` construct to a generator that is then wrapped so it implements `Future`. /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
@ -669,7 +670,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
Ident::with_dummy_span(sym::_task_context), Ident::with_dummy_span(sym::_task_context),
hir::BindingAnnotation::Mutable, hir::BindingAnnotation::Mutable,
); );
let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, ty_span: span, span }; let param = hir::Param { hir_id: self.next_id(), pat, ty_span: span, span };
let params = arena_vec![self; param]; let params = arena_vec![self; param];
let body_id = self.lower_body(move |this| { let body_id = self.lower_body(move |this| {
@ -690,12 +691,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
span, span,
Some(hir::Movability::Static), Some(hir::Movability::Static),
); );
let generator = hir::Expr { let generator =
hir_id: self.lower_node_id(closure_node_id), hir::Expr { hir_id: self.lower_node_id(closure_node_id), kind: generator_kind, span };
kind: generator_kind,
span,
attrs: ThinVec::new(),
};
// `future::from_generator`: // `future::from_generator`:
let unstable_span = let unstable_span =
@ -849,7 +846,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir_id: loop_hir_id, hir_id: loop_hir_id,
kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop, span), kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop, span),
span, span,
attrs: ThinVec::new(),
}); });
// mut pinned => loop { ... } // mut pinned => loop { ... }
@ -1026,7 +1022,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`. // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`.
let destructure_let = self.stmt_let_pat( let destructure_let = self.stmt_let_pat(
ThinVec::new(), None,
whole_span, whole_span,
Some(rhs), Some(rhs),
pat, pat,
@ -1785,7 +1781,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `let mut __next` // `let mut __next`
let next_let = self.stmt_let_pat( let next_let = self.stmt_let_pat(
ThinVec::new(), None,
desugared_span, desugared_span,
None, None,
next_pat, next_pat,
@ -1795,7 +1791,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `let <pat> = __next` // `let <pat> = __next`
let pat = self.lower_pat(pat); let pat = self.lower_pat(pat);
let pat_let = self.stmt_let_pat( let pat_let = self.stmt_let_pat(
ThinVec::new(), None,
desugared_span, desugared_span,
Some(next_expr), Some(next_expr),
pat, pat,
@ -1819,12 +1815,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::LoopSource::ForLoop, hir::LoopSource::ForLoop,
e.span.with_hi(orig_head_span.hi()), e.span.with_hi(orig_head_span.hi()),
); );
let loop_expr = self.arena.alloc(hir::Expr { let loop_expr =
hir_id: self.lower_node_id(e.id), self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: e.span });
kind,
span: e.span,
attrs: ThinVec::new(),
});
// `mut iter => { ... }` // `mut iter => { ... }`
let iter_arm = self.arm(iter_pat, loop_expr); let iter_arm = self.arm(iter_pat, loop_expr);
@ -2159,7 +2151,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
kind: hir::ExprKind<'hir>, kind: hir::ExprKind<'hir>,
attrs: AttrVec, attrs: AttrVec,
) -> hir::Expr<'hir> { ) -> hir::Expr<'hir> {
hir::Expr { hir_id: self.next_id(), kind, span, attrs } let hir_id = self.next_id();
self.lower_attrs(hir_id, &attrs);
hir::Expr { hir_id, kind, span }
} }
fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> { fn field(&mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span) -> hir::Field<'hir> {
@ -2167,13 +2161,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> { fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
hir::Arm { hir::Arm { hir_id: self.next_id(), pat, guard: None, span: expr.span, body: expr }
hir_id: self.next_id(),
attrs: &[],
pat,
guard: None,
span: expr.span,
body: expr,
}
} }
} }

View file

@ -217,44 +217,41 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> { pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
let mut ident = i.ident; let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None); let mut vis = self.lower_visibility(&i.vis, None);
let attrs = self.lower_attrs(&i.attrs);
if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind { if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) { if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) {
let def_id = self.lower_node_id(i.id).expect_owner(); let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
let body = P(self.lower_mac_args(body)); let body = P(self.lower_mac_args(body));
self.exported_macros.push(hir::MacroDef { self.exported_macros.push(hir::MacroDef {
ident, ident,
vis, vis,
attrs, def_id: hir_id.expect_owner(),
def_id,
span: i.span, span: i.span,
ast: MacroDef { body, macro_rules }, ast: MacroDef { body, macro_rules },
}); });
} else { } else {
self.non_exported_macro_attrs.extend(attrs.iter().cloned()); for a in i.attrs.iter() {
let a = self.lower_attr(a);
self.non_exported_macro_attrs.push(a);
}
} }
return None; return None;
} }
let kind = self.lower_item_kind(i.span, i.id, &mut ident, attrs, &mut vis, &i.kind); let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
Some(hir::Item { let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
def_id: self.lower_node_id(i.id).expect_owner(), Some(hir::Item { def_id: hir_id.expect_owner(), ident, kind, vis, span: i.span })
ident,
attrs,
kind,
vis,
span: i.span,
})
} }
fn lower_item_kind( fn lower_item_kind(
&mut self, &mut self,
span: Span, span: Span,
id: NodeId, id: NodeId,
hir_id: hir::HirId,
ident: &mut Ident, ident: &mut Ident,
attrs: &'hir [Attribute], attrs: Option<&'hir [Attribute]>,
vis: &mut hir::Visibility<'hir>, vis: &mut hir::Visibility<'hir>,
i: &ItemKind, i: &ItemKind,
) -> hir::ItemKind<'hir> { ) -> hir::ItemKind<'hir> {
@ -365,14 +362,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(generics, ImplTraitContext::disallowed()), self.lower_generics(generics, ImplTraitContext::disallowed()),
), ),
ItemKind::Struct(ref struct_def, ref generics) => { ItemKind::Struct(ref struct_def, ref generics) => {
let struct_def = self.lower_variant_data(struct_def); let struct_def = self.lower_variant_data(hir_id, struct_def);
hir::ItemKind::Struct( hir::ItemKind::Struct(
struct_def, struct_def,
self.lower_generics(generics, ImplTraitContext::disallowed()), self.lower_generics(generics, ImplTraitContext::disallowed()),
) )
} }
ItemKind::Union(ref vdata, ref generics) => { ItemKind::Union(ref vdata, ref generics) => {
let vdata = self.lower_variant_data(vdata); let vdata = self.lower_variant_data(hir_id, vdata);
hir::ItemKind::Union( hir::ItemKind::Union(
vdata, vdata,
self.lower_generics(generics, ImplTraitContext::disallowed()), self.lower_generics(generics, ImplTraitContext::disallowed()),
@ -505,7 +502,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
id: NodeId, id: NodeId,
vis: &mut hir::Visibility<'hir>, vis: &mut hir::Visibility<'hir>,
ident: &mut Ident, ident: &mut Ident,
attrs: &'hir [Attribute], attrs: Option<&'hir [Attribute]>,
) -> hir::ItemKind<'hir> { ) -> hir::ItemKind<'hir> {
debug!("lower_use_tree(tree={:?})", tree); debug!("lower_use_tree(tree={:?})", tree);
debug!("lower_use_tree: vis = {:?}", vis); debug!("lower_use_tree: vis = {:?}", vis);
@ -554,11 +551,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None); let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single); let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
let vis = this.rebuild_vis(&vis); let vis = this.rebuild_vis(&vis);
if let Some(attrs) = attrs {
this.attrs.insert(new_id, attrs);
}
this.insert_item(hir::Item { this.insert_item(hir::Item {
def_id: new_id.expect_owner(), def_id: new_id.expect_owner(),
ident, ident,
attrs,
kind, kind,
vis, vis,
span, span,
@ -626,11 +625,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let kind = let kind =
this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs); this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
if let Some(attrs) = attrs {
this.attrs.insert(new_hir_id, attrs);
}
this.insert_item(hir::Item { this.insert_item(hir::Item {
def_id: new_hir_id.expect_owner(), def_id: new_hir_id.expect_owner(),
ident, ident,
attrs,
kind, kind,
vis, vis,
span: use_tree.span, span: use_tree.span,
@ -699,11 +700,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
let def_id = self.resolver.local_def_id(i.id); let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
hir::ForeignItem { hir::ForeignItem {
def_id, def_id,
ident: i.ident, ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
kind: match i.kind { kind: match i.kind {
ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => { ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
let fdec = &sig.decl; let fdec = &sig.decl;
@ -748,29 +750,43 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> { fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> {
let id = self.lower_node_id(v.id);
self.lower_attrs(id, &v.attrs);
hir::Variant { hir::Variant {
attrs: self.lower_attrs(&v.attrs), id,
data: self.lower_variant_data(&v.data), data: self.lower_variant_data(id, &v.data),
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
id: self.lower_node_id(v.id),
ident: v.ident, ident: v.ident,
span: v.span, span: v.span,
} }
} }
fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData<'hir> { fn lower_variant_data(
&mut self,
parent_id: hir::HirId,
vdata: &VariantData,
) -> hir::VariantData<'hir> {
match *vdata { match *vdata {
VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct( VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
self.arena self.arena
.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_struct_field(f))), .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_struct_field(f))),
recovered, recovered,
), ),
VariantData::Tuple(ref fields, id) => hir::VariantData::Tuple( VariantData::Tuple(ref fields, id) => {
self.arena let ctor_id = self.lower_node_id(id);
.alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_struct_field(f))), self.alias_attrs(ctor_id, parent_id);
self.lower_node_id(id), hir::VariantData::Tuple(
self.arena.alloc_from_iter(
fields.iter().enumerate().map(|f| self.lower_struct_field(f)),
), ),
VariantData::Unit(id) => hir::VariantData::Unit(self.lower_node_id(id)), ctor_id,
)
}
VariantData::Unit(id) => {
let ctor_id = self.lower_node_id(id);
self.alias_attrs(ctor_id, parent_id);
hir::VariantData::Unit(ctor_id)
}
} }
} }
@ -787,9 +803,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
} else { } else {
self.lower_ty(&f.ty, ImplTraitContext::disallowed()) self.lower_ty(&f.ty, ImplTraitContext::disallowed())
}; };
let hir_id = self.lower_node_id(f.id);
self.lower_attrs(hir_id, &f.attrs);
hir::StructField { hir::StructField {
span: f.span, span: f.span,
hir_id: self.lower_node_id(f.id), hir_id,
ident: match f.ident { ident: match f.ident {
Some(ident) => ident, Some(ident) => ident,
// FIXME(jseyfried): positional field hygiene. // FIXME(jseyfried): positional field hygiene.
@ -797,12 +815,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
}, },
vis: self.lower_visibility(&f.vis, None), vis: self.lower_visibility(&f.vis, None),
ty, ty,
attrs: self.lower_attrs(&f.attrs),
} }
} }
fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
let trait_item_def_id = self.resolver.local_def_id(i.id); let hir_id = self.lower_node_id(i.id);
let trait_item_def_id = hir_id.expect_owner();
let (generics, kind) = match i.kind { let (generics, kind) = match i.kind {
AssocItemKind::Const(_, ref ty, ref default) => { AssocItemKind::Const(_, ref ty, ref default) => {
@ -835,14 +853,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
}; };
hir::TraitItem { self.lower_attrs(hir_id, &i.attrs);
def_id: trait_item_def_id, hir::TraitItem { def_id: trait_item_def_id, ident: i.ident, generics, kind, span: i.span }
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
generics,
kind,
span: i.span,
}
} }
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
@ -920,10 +932,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Since `default impl` is not yet implemented, this is always true in impls. // Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true; let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
hir::ImplItem { hir::ImplItem {
def_id: self.lower_node_id(i.id).expect_owner(), def_id: hir_id.expect_owner(),
ident: i.ident, ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
generics, generics,
vis: self.lower_visibility(&i.vis, None), vis: self.lower_visibility(&i.vis, None),
defaultness, defaultness,
@ -1024,9 +1037,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
let hir_id = self.lower_node_id(param.id);
self.lower_attrs(hir_id, &param.attrs);
hir::Param { hir::Param {
attrs: self.lower_attrs(&param.attrs), hir_id,
hir_id: self.lower_node_id(param.id),
pat: self.lower_pat(&param.pat), pat: self.lower_pat(&param.pat),
ty_span: param.ty.span, ty_span: param.ty.span,
span: param.span, span: param.span,
@ -1158,11 +1172,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// //
// If this is the simple case, this parameter will end up being the same as the // If this is the simple case, this parameter will end up being the same as the
// original parameter, but with a different pattern id. // original parameter, but with a different pattern id.
let mut stmt_attrs = AttrVec::new(); let stmt_attrs = this.attrs.get(&parameter.hir_id).copied();
stmt_attrs.extend(parameter.attrs.iter().cloned());
let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident); let (new_parameter_pat, new_parameter_id) = this.pat_ident(desugared_span, ident);
let new_parameter = hir::Param { let new_parameter = hir::Param {
attrs: parameter.attrs,
hir_id: parameter.hir_id, hir_id: parameter.hir_id,
pat: new_parameter_pat, pat: new_parameter_pat,
ty_span: parameter.ty_span, ty_span: parameter.ty_span,
@ -1205,7 +1217,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id); let move_expr = this.expr_ident(desugared_span, ident, new_parameter_id);
let move_stmt = this.stmt_let_pat( let move_stmt = this.stmt_let_pat(
AttrVec::new(), None,
desugared_span, desugared_span,
Some(move_expr), Some(move_expr),
move_pat, move_pat,

View file

@ -114,6 +114,8 @@ struct LoweringContext<'a, 'hir: 'a> {
generator_kind: Option<hir::GeneratorKind>, generator_kind: Option<hir::GeneratorKind>,
attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
/// When inside an `async` context, this is the `HirId` of the /// When inside an `async` context, this is the `HirId` of the
/// `task_context` local bound to the resume argument of the generator. /// `task_context` local bound to the resume argument of the generator.
task_context: Option<hir::HirId>, task_context: Option<hir::HirId>,
@ -309,6 +311,7 @@ pub fn lower_crate<'a, 'hir>(
bodies: BTreeMap::new(), bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(), trait_impls: BTreeMap::new(),
modules: BTreeMap::new(), modules: BTreeMap::new(),
attrs: BTreeMap::default(),
exported_macros: Vec::new(), exported_macros: Vec::new(),
non_exported_macro_attrs: Vec::new(), non_exported_macro_attrs: Vec::new(),
catch_scopes: Vec::new(), catch_scopes: Vec::new(),
@ -565,7 +568,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
let module = self.lower_mod(&c.items, c.span); let module = self.lower_mod(&c.items, c.span);
let attrs = self.lower_attrs(&c.attrs); self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
let body_ids = body_ids(&self.bodies); let body_ids = body_ids(&self.bodies);
let proc_macros = let proc_macros =
c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect(); c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
@ -592,8 +595,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.resolver.definitions().init_def_id_to_hir_id_mapping(def_id_to_hir_id); self.resolver.definitions().init_def_id_to_hir_id_mapping(def_id_to_hir_id);
#[cfg(debug_assertions)]
for (&id, attrs) in self.attrs.iter() {
// Verify that we do not store empty slices in the map.
if attrs.is_empty() {
panic!("Stored empty attributes for {:?}", id);
}
}
hir::Crate { hir::Crate {
item: hir::CrateItem { module, attrs, span: c.span }, item: hir::CrateItem { module, span: c.span },
exported_macros: self.arena.alloc_from_iter(self.exported_macros), exported_macros: self.arena.alloc_from_iter(self.exported_macros),
non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
items: self.items, items: self.items,
@ -606,6 +617,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
modules: self.modules, modules: self.modules,
proc_macros, proc_macros,
trait_map, trait_map,
attrs: self.attrs,
} }
} }
@ -834,7 +846,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::GenericParam { hir::GenericParam {
hir_id: self.lower_node_id(node_id), hir_id: self.lower_node_id(node_id),
name: hir_name, name: hir_name,
attrs: &[],
bounds: &[], bounds: &[],
span, span,
pure_wrt_drop: false, pure_wrt_drop: false,
@ -967,11 +978,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ret ret
} }
fn lower_attrs(&mut self, attrs: &[Attribute]) -> &'hir [Attribute] { fn lower_attrs(&mut self, id: hir::HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a))) if attrs.is_empty() {
None
} else {
let ret = self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)));
debug_assert!(!ret.is_empty());
self.attrs.insert(id, ret);
Some(ret)
}
} }
fn lower_attr(&mut self, attr: &Attribute) -> Attribute { fn lower_attr(&self, attr: &Attribute) -> Attribute {
// Note that we explicitly do not walk the path. Since we don't really // Note that we explicitly do not walk the path. Since we don't really
// lower attributes (we use the AST version) there is nowhere to keep // lower attributes (we use the AST version) there is nowhere to keep
// the `HirId`s. We don't actually need HIR version of attributes anyway. // the `HirId`s. We don't actually need HIR version of attributes anyway.
@ -991,7 +1009,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Attribute { kind, id: attr.id, style: attr.style, span: attr.span } Attribute { kind, id: attr.id, style: attr.style, span: attr.span }
} }
fn lower_mac_args(&mut self, args: &MacArgs) -> MacArgs { fn alias_attrs(&mut self, id: hir::HirId, target_id: hir::HirId) {
if let Some(&a) = self.attrs.get(&target_id) {
debug_assert!(!a.is_empty());
self.attrs.insert(id, a);
}
}
fn lower_mac_args(&self, args: &MacArgs) -> MacArgs {
match *args { match *args {
MacArgs::Empty => MacArgs::Empty, MacArgs::Empty => MacArgs::Empty,
MacArgs::Delimited(dspan, delim, ref tokens) => { MacArgs::Delimited(dspan, delim, ref tokens) => {
@ -1444,7 +1469,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir_id: self.lower_node_id(def_node_id), hir_id: self.lower_node_id(def_node_id),
name: ParamName::Plain(ident), name: ParamName::Plain(ident),
pure_wrt_drop: false, pure_wrt_drop: false,
attrs: &[],
bounds: hir_bounds, bounds: hir_bounds,
span, span,
kind: hir::GenericParamKind::Type { kind: hir::GenericParamKind::Type {
@ -1572,7 +1596,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let opaque_ty_item = hir::Item { let opaque_ty_item = hir::Item {
def_id: opaque_ty_id, def_id: opaque_ty_id,
ident: Ident::invalid(), ident: Ident::invalid(),
attrs: Default::default(),
kind: opaque_ty_item_kind, kind: opaque_ty_item_kind,
vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited), vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
span: opaque_ty_span, span: opaque_ty_span,
@ -1733,7 +1756,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
name, name,
span: lifetime.span, span: lifetime.span,
pure_wrt_drop: false, pure_wrt_drop: false,
attrs: &[],
bounds: &[], bounds: &[],
kind: hir::GenericParamKind::Lifetime { kind }, kind: hir::GenericParamKind::Lifetime { kind },
}); });
@ -1790,14 +1812,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
}); });
let init = l.init.as_ref().map(|e| self.lower_expr(e)); let init = l.init.as_ref().map(|e| self.lower_expr(e));
let hir_id = self.lower_node_id(l.id);
self.lower_attrs(hir_id, &l.attrs);
( (
hir::Local { hir::Local {
hir_id: self.lower_node_id(l.id), hir_id,
ty, ty,
pat: self.lower_pat(&l.pat), pat: self.lower_pat(&l.pat),
init, init,
span: l.span, span: l.span,
attrs: l.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
source: hir::LocalSource::Normal, source: hir::LocalSource::Normal,
}, },
ids, ids,
@ -2300,12 +2323,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
}; };
let hir_id = self.lower_node_id(param.id);
self.lower_attrs(hir_id, &param.attrs);
hir::GenericParam { hir::GenericParam {
hir_id: self.lower_node_id(param.id), hir_id,
name, name,
span: param.ident.span, span: param.ident.span,
pure_wrt_drop: self.sess.contains_name(&param.attrs, sym::may_dangle), pure_wrt_drop: self.sess.contains_name(&param.attrs, sym::may_dangle),
attrs: self.lower_attrs(&param.attrs),
bounds: self.arena.alloc_from_iter(bounds), bounds: self.arena.alloc_from_iter(bounds),
kind, kind,
} }
@ -2426,7 +2450,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> { fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> {
let kind = match s.kind { let (hir_id, kind) = match s.kind {
StmtKind::Local(ref l) => { StmtKind::Local(ref l) => {
let (l, item_ids) = self.lower_local(l); let (l, item_ids) = self.lower_local(l);
let mut ids: SmallVec<[hir::Stmt<'hir>; 1]> = item_ids let mut ids: SmallVec<[hir::Stmt<'hir>; 1]> = item_ids
@ -2439,9 +2463,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.stmt(s.span, hir::StmtKind::Item(item_id)) self.stmt(s.span, hir::StmtKind::Item(item_id))
}) })
.collect(); .collect();
let hir_id = self.lower_node_id(s.id);
self.alias_attrs(hir_id, l.hir_id);
ids.push({ ids.push({
hir::Stmt { hir::Stmt {
hir_id: self.lower_node_id(s.id), hir_id,
kind: hir::StmtKind::Local(self.arena.alloc(l)), kind: hir::StmtKind::Local(self.arena.alloc(l)),
span: s.span, span: s.span,
} }
@ -2464,12 +2490,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}) })
.collect(); .collect();
} }
StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.lower_expr(e)), StmtKind::Expr(ref e) => {
StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.lower_expr(e)), let e = self.lower_expr(e);
let hir_id = self.lower_node_id(s.id);
self.alias_attrs(hir_id, e.hir_id);
(hir_id, hir::StmtKind::Expr(e))
}
StmtKind::Semi(ref e) => {
let e = self.lower_expr(e);
let hir_id = self.lower_node_id(s.id);
self.alias_attrs(hir_id, e.hir_id);
(hir_id, hir::StmtKind::Semi(e))
}
StmtKind::Empty => return smallvec![], StmtKind::Empty => return smallvec![],
StmtKind::MacCall(..) => panic!("shouldn't exist here"), StmtKind::MacCall(..) => panic!("shouldn't exist here"),
}; };
smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }] smallvec![hir::Stmt { hir_id, kind, span: s.span }]
} }
fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
@ -2513,13 +2549,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn stmt_let_pat( fn stmt_let_pat(
&mut self, &mut self,
attrs: AttrVec, attrs: Option<&'hir [Attribute]>,
span: Span, span: Span,
init: Option<&'hir hir::Expr<'hir>>, init: Option<&'hir hir::Expr<'hir>>,
pat: &'hir hir::Pat<'hir>, pat: &'hir hir::Pat<'hir>,
source: hir::LocalSource, source: hir::LocalSource,
) -> hir::Stmt<'hir> { ) -> hir::Stmt<'hir> {
let local = hir::Local { attrs, hir_id: self.next_id(), init, pat, source, span, ty: None }; let hir_id = self.next_id();
if let Some(a) = attrs {
debug_assert!(!a.is_empty());
self.attrs.insert(hir_id, a);
}
let local = hir::Local { hir_id, init, pat, source, span, ty: None };
self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local))) self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local)))
} }

View file

@ -433,12 +433,10 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
let sess = tcx.sess; let sess = tcx.sess;
let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_name = tcx.crate_name(LOCAL_CRATE);
let no_builtins = tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins); let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let is_compiler_builtins = let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::compiler_builtins); let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
let subsystem = tcx let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
.sess
.first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem);
let windows_subsystem = subsystem.map(|subsystem| { let windows_subsystem = subsystem.map(|subsystem| {
if subsystem != sym::windows && subsystem != sym::console { if subsystem != sym::windows && subsystem != sym::console {
tcx.sess.fatal(&format!( tcx.sess.fatal(&format!(

View file

@ -6,7 +6,7 @@ use crate::{itemlikevisit, LangItem};
use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect}; use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect};
use rustc_ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy}; use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability}; pub use rustc_ast::{CaptureBy, Movability, Mutability};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@ -469,7 +469,6 @@ pub enum GenericParamKind<'hir> {
pub struct GenericParam<'hir> { pub struct GenericParam<'hir> {
pub hir_id: HirId, pub hir_id: HirId,
pub name: ParamName, pub name: ParamName,
pub attrs: &'hir [Attribute],
pub bounds: GenericBounds<'hir>, pub bounds: GenericBounds<'hir>,
pub span: Span, pub span: Span,
pub pure_wrt_drop: bool, pub pure_wrt_drop: bool,
@ -630,7 +629,6 @@ pub struct ModuleItems {
#[derive(Encodable, Debug, HashStable_Generic)] #[derive(Encodable, Debug, HashStable_Generic)]
pub struct CrateItem<'hir> { pub struct CrateItem<'hir> {
pub module: Mod<'hir>, pub module: Mod<'hir>,
pub attrs: &'hir [Attribute],
pub span: Span, pub span: Span,
} }
@ -675,6 +673,9 @@ pub struct Crate<'hir> {
pub proc_macros: Vec<HirId>, pub proc_macros: Vec<HirId>,
pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>, pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
/// Collected attributes from HIR nodes.
pub attrs: BTreeMap<HirId, &'hir [Attribute]>,
} }
impl Crate<'hir> { impl Crate<'hir> {
@ -766,7 +767,6 @@ impl Crate<'_> {
pub struct MacroDef<'hir> { pub struct MacroDef<'hir> {
pub ident: Ident, pub ident: Ident,
pub vis: Visibility<'hir>, pub vis: Visibility<'hir>,
pub attrs: &'hir [Attribute],
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub span: Span, pub span: Span,
pub ast: ast::MacroDef, pub ast: ast::MacroDef,
@ -1166,16 +1166,6 @@ pub enum StmtKind<'hir> {
Semi(&'hir Expr<'hir>), Semi(&'hir Expr<'hir>),
} }
impl<'hir> StmtKind<'hir> {
pub fn attrs(&self, get_item: impl FnOnce(ItemId) -> &'hir Item<'hir>) -> &'hir [Attribute] {
match *self {
StmtKind::Local(ref l) => &l.attrs,
StmtKind::Item(ref item_id) => &get_item(*item_id).attrs,
StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => &e.attrs,
}
}
}
/// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`). /// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub struct Local<'hir> { pub struct Local<'hir> {
@ -1186,7 +1176,6 @@ pub struct Local<'hir> {
pub init: Option<&'hir Expr<'hir>>, pub init: Option<&'hir Expr<'hir>>,
pub hir_id: HirId, pub hir_id: HirId,
pub span: Span, pub span: Span,
pub attrs: AttrVec,
/// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
/// desugaring. Otherwise will be `Normal`. /// desugaring. Otherwise will be `Normal`.
pub source: LocalSource, pub source: LocalSource,
@ -1199,7 +1188,6 @@ pub struct Arm<'hir> {
#[stable_hasher(ignore)] #[stable_hasher(ignore)]
pub hir_id: HirId, pub hir_id: HirId,
pub span: Span, pub span: Span,
pub attrs: &'hir [Attribute],
/// If this pattern and the optional guard matches, then `body` is evaluated. /// If this pattern and the optional guard matches, then `body` is evaluated.
pub pat: &'hir Pat<'hir>, pub pat: &'hir Pat<'hir>,
/// Optional guard clause. /// Optional guard clause.
@ -1458,7 +1446,6 @@ pub struct AnonConst {
pub struct Expr<'hir> { pub struct Expr<'hir> {
pub hir_id: HirId, pub hir_id: HirId,
pub kind: ExprKind<'hir>, pub kind: ExprKind<'hir>,
pub attrs: AttrVec,
pub span: Span, pub span: Span,
} }
@ -2040,7 +2027,6 @@ impl TraitItemId {
pub struct TraitItem<'hir> { pub struct TraitItem<'hir> {
pub ident: Ident, pub ident: Ident,
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub attrs: &'hir [Attribute],
pub generics: Generics<'hir>, pub generics: Generics<'hir>,
pub kind: TraitItemKind<'hir>, pub kind: TraitItemKind<'hir>,
pub span: Span, pub span: Span,
@ -2103,7 +2089,6 @@ pub struct ImplItem<'hir> {
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub vis: Visibility<'hir>, pub vis: Visibility<'hir>,
pub defaultness: Defaultness, pub defaultness: Defaultness,
pub attrs: &'hir [Attribute],
pub generics: Generics<'hir>, pub generics: Generics<'hir>,
pub kind: ImplItemKind<'hir>, pub kind: ImplItemKind<'hir>,
pub span: Span, pub span: Span,
@ -2433,7 +2418,6 @@ pub struct LlvmInlineAsm<'hir> {
/// Represents a parameter in a function header. /// Represents a parameter in a function header.
#[derive(Debug, HashStable_Generic)] #[derive(Debug, HashStable_Generic)]
pub struct Param<'hir> { pub struct Param<'hir> {
pub attrs: &'hir [Attribute],
pub hir_id: HirId, pub hir_id: HirId,
pub pat: &'hir Pat<'hir>, pub pat: &'hir Pat<'hir>,
pub ty_span: Span, pub ty_span: Span,
@ -2551,8 +2535,6 @@ pub struct Variant<'hir> {
/// Name of the variant. /// Name of the variant.
#[stable_hasher(project(name))] #[stable_hasher(project(name))]
pub ident: Ident, pub ident: Ident,
/// Attributes of the variant.
pub attrs: &'hir [Attribute],
/// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`). /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
pub id: HirId, pub id: HirId,
/// Fields and constructor id of the variant. /// Fields and constructor id of the variant.
@ -2646,7 +2628,6 @@ pub struct StructField<'hir> {
pub vis: Visibility<'hir>, pub vis: Visibility<'hir>,
pub hir_id: HirId, pub hir_id: HirId,
pub ty: &'hir Ty<'hir>, pub ty: &'hir Ty<'hir>,
pub attrs: &'hir [Attribute],
} }
impl StructField<'_> { impl StructField<'_> {
@ -2715,7 +2696,6 @@ impl ItemId {
pub struct Item<'hir> { pub struct Item<'hir> {
pub ident: Ident, pub ident: Ident,
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub attrs: &'hir [Attribute],
pub kind: ItemKind<'hir>, pub kind: ItemKind<'hir>,
pub vis: Visibility<'hir>, pub vis: Visibility<'hir>,
pub span: Span, pub span: Span,
@ -2932,7 +2912,6 @@ pub struct ForeignItemRef<'hir> {
#[derive(Debug)] #[derive(Debug)]
pub struct ForeignItem<'hir> { pub struct ForeignItem<'hir> {
pub ident: Ident, pub ident: Ident,
pub attrs: &'hir [Attribute],
pub kind: ForeignItemKind<'hir>, pub kind: ForeignItemKind<'hir>,
pub def_id: LocalDefId, pub def_id: LocalDefId,
pub span: Span, pub span: Span,
@ -3091,13 +3070,13 @@ impl<'hir> Node<'hir> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts { mod size_asserts {
rustc_data_structures::static_assert_size!(super::Block<'static>, 48); rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
rustc_data_structures::static_assert_size!(super::Expr<'static>, 72); rustc_data_structures::static_assert_size!(super::Expr<'static>, 64);
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88); rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
rustc_data_structures::static_assert_size!(super::Item<'static>, 200); rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 144); rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);
rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 168); rustc_data_structures::static_assert_size!(super::ImplItem<'static>, 152);
rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 152); rustc_data_structures::static_assert_size!(super::ForeignItem<'static>, 136);
} }

View file

@ -1,4 +1,5 @@
use crate::def_id::{LocalDefId, CRATE_DEF_INDEX}; use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
use rustc_index::vec::IndexVec;
use std::fmt; use std::fmt;
/// Uniquely identifies a node in the HIR of the current crate. It is /// Uniquely identifies a node in the HIR of the current crate. It is
@ -61,3 +62,69 @@ pub const CRATE_HIR_ID: HirId = HirId {
owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
local_id: ItemLocalId::from_u32(0), local_id: ItemLocalId::from_u32(0),
}; };
#[derive(Clone, Default, Debug, Encodable, Decodable)]
pub struct HirIdVec<T> {
map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
}
impl<T> HirIdVec<T> {
pub fn push_owner(&mut self, id: LocalDefId) {
self.map.ensure_contains_elem(id, IndexVec::new);
}
pub fn push(&mut self, id: HirId, value: T) {
if id.local_id == ItemLocalId::from_u32(0) {
self.push_owner(id.owner);
}
let submap = &mut self.map[id.owner];
let _ret_id = submap.push(value);
debug_assert_eq!(_ret_id, id.local_id);
}
pub fn push_sparse(&mut self, id: HirId, value: T)
where
T: Default,
{
self.map.ensure_contains_elem(id.owner, IndexVec::new);
let submap = &mut self.map[id.owner];
let i = id.local_id.index();
let len = submap.len();
if i >= len {
submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
}
submap[id.local_id] = value;
}
pub fn get(&self, id: HirId) -> Option<&T> {
self.map.get(id.owner)?.get(id.local_id)
}
pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
&self.map[id]
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.map.iter().flat_map(|la| la.iter())
}
pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
self.map.iter_enumerated().flat_map(|(owner, la)| {
la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
})
}
}
impl<T> std::ops::Index<HirId> for HirIdVec<T> {
type Output = T;
fn index(&self, id: HirId) -> &T {
&self.map[id.owner][id.local_id]
}
}
impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
fn index_mut(&mut self, id: HirId) -> &mut T {
&mut self.map[id.owner][id.local_id]
}
}

View file

@ -101,29 +101,21 @@ where
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
/// `#[xxx] pub async/const/extern "Abi" fn foo()` /// `#[xxx] pub async/const/extern "Abi" fn foo()`
ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>, &'a [Attribute]), ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>),
/// `fn foo(&self)` /// `fn foo(&self)`
Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>, &'a [Attribute]), Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>),
/// `|x, y| {}` /// `|x, y| {}`
Closure(&'a [Attribute]), Closure,
} }
impl<'a> FnKind<'a> { impl<'a> FnKind<'a> {
pub fn attrs(&self) -> &'a [Attribute] {
match *self {
FnKind::ItemFn(.., attrs) => attrs,
FnKind::Method(.., attrs) => attrs,
FnKind::Closure(attrs) => attrs,
}
}
pub fn header(&self) -> Option<&FnHeader> { pub fn header(&self) -> Option<&FnHeader> {
match *self { match *self {
FnKind::ItemFn(_, _, ref header, _, _) => Some(header), FnKind::ItemFn(_, _, ref header, _) => Some(header),
FnKind::Method(_, ref sig, _, _) => Some(&sig.header), FnKind::Method(_, ref sig, _) => Some(&sig.header),
FnKind::Closure(_) => None, FnKind::Closure => None,
} }
} }
} }
@ -466,7 +458,7 @@ pub trait Visitor<'v>: Sized {
fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) { fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
walk_assoc_type_binding(self, type_binding) walk_assoc_type_binding(self, type_binding)
} }
fn visit_attribute(&mut self, _attr: &'v Attribute) {} fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) { fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
walk_macro_def(self, macro_def) walk_macro_def(self, macro_def)
} }
@ -484,14 +476,17 @@ pub trait Visitor<'v>: Sized {
/// Walks the contents of a crate. See also `Crate::visit_all_items`. /// Walks the contents of a crate. See also `Crate::visit_all_items`.
pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID);
walk_list!(visitor, visit_attribute, krate.item.attrs);
walk_list!(visitor, visit_macro_def, krate.exported_macros); walk_list!(visitor, visit_macro_def, krate.exported_macros);
for (&id, attrs) in krate.attrs.iter() {
for a in *attrs {
visitor.visit_attribute(id, a)
}
}
} }
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) { pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
visitor.visit_id(macro_def.hir_id()); visitor.visit_id(macro_def.hir_id());
visitor.visit_ident(macro_def.ident); visitor.visit_ident(macro_def.ident);
walk_list!(visitor, visit_attribute, macro_def.attrs);
} }
pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) { pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
@ -510,7 +505,6 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
// Intentionally visiting the expr first - the initialization expr // Intentionally visiting the expr first - the initialization expr
// dominates the local's definition. // dominates the local's definition.
walk_list!(visitor, visit_expr, &local.init); walk_list!(visitor, visit_expr, &local.init);
walk_list!(visitor, visit_attribute, local.attrs.iter());
visitor.visit_id(local.hir_id); visitor.visit_id(local.hir_id);
visitor.visit_pat(&local.pat); visitor.visit_pat(&local.pat);
walk_list!(visitor, visit_ty, &local.ty); walk_list!(visitor, visit_ty, &local.ty);
@ -557,7 +551,6 @@ pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitR
pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) { pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
visitor.visit_id(param.hir_id); visitor.visit_id(param.hir_id);
visitor.visit_pat(&param.pat); visitor.visit_pat(&param.pat);
walk_list!(visitor, visit_attribute, param.attrs);
} }
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
@ -579,7 +572,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
visitor.visit_nested_body(body); visitor.visit_nested_body(body);
} }
ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn( ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
FnKind::ItemFn(item.ident, generics, sig.header, &item.vis, &item.attrs), FnKind::ItemFn(item.ident, generics, sig.header, &item.vis),
&sig.decl, &sig.decl,
body_id, body_id,
item.span, item.span,
@ -652,7 +645,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_param_bound, bounds);
} }
} }
walk_list!(visitor, visit_attribute, item.attrs);
} }
pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) { pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) {
@ -686,7 +678,6 @@ pub fn walk_variant<'v, V: Visitor<'v>>(
variant.span, variant.span,
); );
walk_list!(visitor, visit_anon_const, &variant.disr_expr); walk_list!(visitor, visit_anon_const, &variant.disr_expr);
walk_list!(visitor, visit_attribute, variant.attrs);
} }
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
@ -851,8 +842,6 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
ForeignItemKind::Type => (), ForeignItemKind::Type => (),
} }
walk_list!(visitor, visit_attribute, foreign_item.attrs);
} }
pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) { pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
@ -870,7 +859,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam<'v>) { pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam<'v>) {
visitor.visit_id(param.hir_id); visitor.visit_id(param.hir_id);
walk_list!(visitor, visit_attribute, param.attrs);
match param.name { match param.name {
ParamName::Plain(ident) => visitor.visit_ident(ident), ParamName::Plain(ident) => visitor.visit_ident(ident),
ParamName::Error | ParamName::Fresh(_) => {} ParamName::Error | ParamName::Fresh(_) => {}
@ -940,7 +928,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
FnKind::ItemFn(_, generics, ..) => { FnKind::ItemFn(_, generics, ..) => {
visitor.visit_generics(generics); visitor.visit_generics(generics);
} }
FnKind::Method(..) | FnKind::Closure(_) => {} FnKind::Method(..) | FnKind::Closure => {}
} }
} }
@ -960,7 +948,6 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) { pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
visitor.visit_ident(trait_item.ident); visitor.visit_ident(trait_item.ident);
walk_list!(visitor, visit_attribute, trait_item.attrs);
visitor.visit_generics(&trait_item.generics); visitor.visit_generics(&trait_item.generics);
match trait_item.kind { match trait_item.kind {
TraitItemKind::Const(ref ty, default) => { TraitItemKind::Const(ref ty, default) => {
@ -977,7 +964,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
} }
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
visitor.visit_fn( visitor.visit_fn(
FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs), FnKind::Method(trait_item.ident, sig, None),
&sig.decl, &sig.decl,
body_id, body_id,
trait_item.span, trait_item.span,
@ -1003,21 +990,12 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) { pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added. // N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem { let ImplItem { def_id: _, ident, ref vis, ref defaultness, ref generics, ref kind, span: _ } =
def_id: _, *impl_item;
ident,
ref vis,
ref defaultness,
attrs,
ref generics,
ref kind,
span: _,
} = *impl_item;
visitor.visit_ident(ident); visitor.visit_ident(ident);
visitor.visit_vis(vis); visitor.visit_vis(vis);
visitor.visit_defaultness(defaultness); visitor.visit_defaultness(defaultness);
walk_list!(visitor, visit_attribute, attrs);
visitor.visit_generics(generics); visitor.visit_generics(generics);
match *kind { match *kind {
ImplItemKind::Const(ref ty, body) => { ImplItemKind::Const(ref ty, body) => {
@ -1027,7 +1005,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
} }
ImplItemKind::Fn(ref sig, body_id) => { ImplItemKind::Fn(ref sig, body_id) => {
visitor.visit_fn( visitor.visit_fn(
FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs), FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)),
&sig.decl, &sig.decl,
body_id, body_id,
impl_item.span, impl_item.span,
@ -1075,7 +1053,6 @@ pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v
visitor.visit_vis(&struct_field.vis); visitor.visit_vis(&struct_field.vis);
visitor.visit_ident(struct_field.ident); visitor.visit_ident(struct_field.ident);
visitor.visit_ty(&struct_field.ty); visitor.visit_ty(&struct_field.ty);
walk_list!(visitor, visit_attribute, struct_field.attrs);
} }
pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) { pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
@ -1102,7 +1079,6 @@ pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonCo
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
visitor.visit_id(expression.hir_id); visitor.visit_id(expression.hir_id);
walk_list!(visitor, visit_attribute, expression.attrs.iter());
match expression.kind { match expression.kind {
ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
ExprKind::Array(subexpressions) => { ExprKind::Array(subexpressions) => {
@ -1162,7 +1138,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
} }
ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
.visit_fn( .visit_fn(
FnKind::Closure(&expression.attrs), FnKind::Closure,
function_declaration, function_declaration,
body, body,
expression.span, expression.span,
@ -1246,7 +1222,6 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
} }
} }
visitor.visit_expr(&arm.body); visitor.visit_expr(&arm.body);
walk_list!(visitor, visit_attribute, arm.attrs);
} }
pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) { pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) {

View file

@ -139,11 +139,10 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for VisibilityKind<'_>
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> { impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
let TraitItem { def_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; let TraitItem { def_id: _, ident, ref generics, ref kind, span } = *self;
hcx.hash_hir_item_like(|hcx| { hcx.hash_hir_item_like(|hcx| {
ident.name.hash_stable(hcx, hasher); ident.name.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
generics.hash_stable(hcx, hasher); generics.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher); kind.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);
@ -153,22 +152,13 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> { impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
let ImplItem { let ImplItem { def_id: _, ident, ref vis, defaultness, ref generics, ref kind, span } =
def_id: _, *self;
ident,
ref vis,
defaultness,
ref attrs,
ref generics,
ref kind,
span,
} = *self;
hcx.hash_hir_item_like(|hcx| { hcx.hash_hir_item_like(|hcx| {
ident.name.hash_stable(hcx, hasher); ident.name.hash_stable(hcx, hasher);
vis.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher);
defaultness.hash_stable(hcx, hasher); defaultness.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
generics.hash_stable(hcx, hasher); generics.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher); kind.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);
@ -178,11 +168,10 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItem<'_> { impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItem<'_> {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
let ForeignItem { def_id: _, ident, ref attrs, ref kind, span, ref vis } = *self; let ForeignItem { def_id: _, ident, ref kind, span, ref vis } = *self;
hcx.hash_hir_item_like(|hcx| { hcx.hash_hir_item_like(|hcx| {
ident.name.hash_stable(hcx, hasher); ident.name.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher); kind.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);
vis.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher);
@ -192,11 +181,10 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ForeignItem<'_> {
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> { impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
let Item { ident, ref attrs, def_id: _, ref kind, ref vis, span } = *self; let Item { ident, def_id: _, ref kind, ref vis, span } = *self;
hcx.hash_hir_item_like(|hcx| { hcx.hash_hir_item_like(|hcx| {
ident.name.hash_stable(hcx, hasher); ident.name.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher); kind.hash_stable(hcx, hasher);
vis.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);
@ -206,11 +194,10 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for MacroDef<'_> { impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for MacroDef<'_> {
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
let MacroDef { ident, ref attrs, def_id: _, ref ast, ref vis, span } = *self; let MacroDef { ident, def_id: _, ref ast, ref vis, span } = *self;
hcx.hash_hir_item_like(|hcx| { hcx.hash_hir_item_like(|hcx| {
ident.name.hash_stable(hcx, hasher); ident.name.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
ast.hash_stable(hcx, hasher); ast.hash_stable(hcx, hasher);
vis.hash_stable(hcx, hasher); vis.hash_stable(hcx, hasher);
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);

View file

@ -16,6 +16,7 @@ use rustc_target::spec::abi::Abi;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::Cell; use std::cell::Cell;
use std::collections::BTreeMap;
use std::vec; use std::vec;
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String { pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String {
@ -82,6 +83,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
pub struct State<'a> { pub struct State<'a> {
pub s: pp::Printer, pub s: pp::Printer,
comments: Option<Comments<'a>>, comments: Option<Comments<'a>>,
attrs: &'a BTreeMap<hir::HirId, &'a [ast::Attribute]>,
ann: &'a (dyn PpAnn + 'a), ann: &'a (dyn PpAnn + 'a),
} }
@ -163,12 +165,12 @@ pub fn print_crate<'a>(
input: String, input: String,
ann: &'a dyn PpAnn, ann: &'a dyn PpAnn,
) -> String { ) -> String {
let mut s = State::new_from_input(sm, filename, input, ann); let mut s = State::new_from_input(sm, filename, input, &krate.attrs, ann);
// When printing the AST, we sometimes need to inject `#[no_std]` here. // When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary. // Since you can't compile the HIR, it's not necessary.
s.print_mod(&krate.item.module, &krate.item.attrs); s.print_mod(&krate.item.module, s.attrs(hir::CRATE_HIR_ID));
s.print_remaining_comments(); s.print_remaining_comments();
s.s.eof() s.s.eof()
} }
@ -178,9 +180,19 @@ impl<'a> State<'a> {
sm: &'a SourceMap, sm: &'a SourceMap,
filename: FileName, filename: FileName,
input: String, input: String,
attrs: &'a BTreeMap<hir::HirId, &[ast::Attribute]>,
ann: &'a dyn PpAnn, ann: &'a dyn PpAnn,
) -> State<'a> { ) -> State<'a> {
State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann } State {
s: pp::mk_printer(),
comments: Some(Comments::new(sm, filename, input)),
attrs,
ann,
}
}
fn attrs(&self, id: hir::HirId) -> &'a [ast::Attribute] {
self.attrs.get(&id).map_or(&[], |la| *la)
} }
} }
@ -188,7 +200,8 @@ pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
where where
F: FnOnce(&mut State<'_>), F: FnOnce(&mut State<'_>),
{ {
let mut printer = State { s: pp::mk_printer(), comments: None, ann }; let mut printer =
State { s: pp::mk_printer(), comments: None, attrs: &BTreeMap::default(), ann };
f(&mut printer); f(&mut printer);
printer.s.eof() printer.s.eof()
} }
@ -441,7 +454,7 @@ impl<'a> State<'a> {
pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) { pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo()); self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs); self.print_outer_attributes(self.attrs(item.hir_id()));
match item.kind { match item.kind {
hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => { hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => {
self.head(""); self.head("");
@ -549,7 +562,8 @@ impl<'a> State<'a> {
pub fn print_item(&mut self, item: &hir::Item<'_>) { pub fn print_item(&mut self, item: &hir::Item<'_>) {
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(item.span.lo()); self.maybe_print_comment(item.span.lo());
self.print_outer_attributes(&item.attrs); let attrs = self.attrs(item.hir_id());
self.print_outer_attributes(attrs);
self.ann.pre(self, AnnNode::Item(item)); self.ann.pre(self, AnnNode::Item(item));
match item.kind { match item.kind {
hir::ItemKind::ExternCrate(orig_name) => { hir::ItemKind::ExternCrate(orig_name) => {
@ -634,14 +648,14 @@ impl<'a> State<'a> {
self.print_ident(item.ident); self.print_ident(item.ident);
self.nbsp(); self.nbsp();
self.bopen(); self.bopen();
self.print_mod(_mod, &item.attrs); self.print_mod(_mod, attrs);
self.bclose(item.span); self.bclose(item.span);
} }
hir::ItemKind::ForeignMod { abi, items } => { hir::ItemKind::ForeignMod { abi, items } => {
self.head("extern"); self.head("extern");
self.word_nbsp(abi.to_string()); self.word_nbsp(abi.to_string());
self.bopen(); self.bopen();
self.print_inner_attributes(item.attrs); self.print_inner_attributes(self.attrs(item.hir_id()));
for item in items { for item in items {
self.ann.nested(self, Nested::ForeignItem(item.id)); self.ann.nested(self, Nested::ForeignItem(item.id));
} }
@ -725,7 +739,7 @@ impl<'a> State<'a> {
self.s.space(); self.s.space();
self.bopen(); self.bopen();
self.print_inner_attributes(&item.attrs); self.print_inner_attributes(attrs);
for impl_item in items { for impl_item in items {
self.ann.nested(self, Nested::ImplItem(impl_item.id)); self.ann.nested(self, Nested::ImplItem(impl_item.id));
} }
@ -822,7 +836,7 @@ impl<'a> State<'a> {
for v in variants { for v in variants {
self.space_if_not_bol(); self.space_if_not_bol();
self.maybe_print_comment(v.span.lo()); self.maybe_print_comment(v.span.lo());
self.print_outer_attributes(&v.attrs); self.print_outer_attributes(self.attrs(v.id));
self.ibox(INDENT_UNIT); self.ibox(INDENT_UNIT);
self.print_variant(v); self.print_variant(v);
self.s.word(","); self.s.word(",");
@ -876,7 +890,7 @@ impl<'a> State<'a> {
self.popen(); self.popen();
self.commasep(Inconsistent, struct_def.fields(), |s, field| { self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo()); s.maybe_print_comment(field.span.lo());
s.print_outer_attributes(&field.attrs); s.print_outer_attributes(s.attrs(field.hir_id));
s.print_visibility(&field.vis); s.print_visibility(&field.vis);
s.print_type(&field.ty) s.print_type(&field.ty)
}); });
@ -898,7 +912,7 @@ impl<'a> State<'a> {
for field in struct_def.fields() { for field in struct_def.fields() {
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(field.span.lo()); self.maybe_print_comment(field.span.lo());
self.print_outer_attributes(&field.attrs); self.print_outer_attributes(self.attrs(field.hir_id));
self.print_visibility(&field.vis); self.print_visibility(&field.vis);
self.print_ident(field.ident); self.print_ident(field.ident);
self.word_nbsp(":"); self.word_nbsp(":");
@ -937,7 +951,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::SubItem(ti.hir_id())); self.ann.pre(self, AnnNode::SubItem(ti.hir_id()));
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(ti.span.lo()); self.maybe_print_comment(ti.span.lo());
self.print_outer_attributes(&ti.attrs); self.print_outer_attributes(self.attrs(ti.hir_id()));
match ti.kind { match ti.kind {
hir::TraitItemKind::Const(ref ty, default) => { hir::TraitItemKind::Const(ref ty, default) => {
let vis = let vis =
@ -976,7 +990,7 @@ impl<'a> State<'a> {
self.ann.pre(self, AnnNode::SubItem(ii.hir_id())); self.ann.pre(self, AnnNode::SubItem(ii.hir_id()));
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(ii.span.lo()); self.maybe_print_comment(ii.span.lo());
self.print_outer_attributes(&ii.attrs); self.print_outer_attributes(self.attrs(ii.hir_id()));
self.print_defaultness(ii.defaultness); self.print_defaultness(ii.defaultness);
match ii.kind { match ii.kind {
@ -1321,7 +1335,7 @@ impl<'a> State<'a> {
pub fn print_expr(&mut self, expr: &hir::Expr<'_>) { pub fn print_expr(&mut self, expr: &hir::Expr<'_>) {
self.maybe_print_comment(expr.span.lo()); self.maybe_print_comment(expr.span.lo());
self.print_outer_attributes(&expr.attrs); self.print_outer_attributes(self.attrs(expr.hir_id));
self.ibox(INDENT_UNIT); self.ibox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Expr(expr)); self.ann.pre(self, AnnNode::Expr(expr));
match expr.kind { match expr.kind {
@ -2020,20 +2034,20 @@ impl<'a> State<'a> {
} }
pub fn print_param(&mut self, arg: &hir::Param<'_>) { pub fn print_param(&mut self, arg: &hir::Param<'_>) {
self.print_outer_attributes(&arg.attrs); self.print_outer_attributes(self.attrs(arg.hir_id));
self.print_pat(&arg.pat); self.print_pat(&arg.pat);
} }
pub fn print_arm(&mut self, arm: &hir::Arm<'_>) { pub fn print_arm(&mut self, arm: &hir::Arm<'_>) {
// I have no idea why this check is necessary, but here it // I have no idea why this check is necessary, but here it
// is :( // is :(
if arm.attrs.is_empty() { if self.attrs(arm.hir_id).is_empty() {
self.s.space(); self.s.space();
} }
self.cbox(INDENT_UNIT); self.cbox(INDENT_UNIT);
self.ann.pre(self, AnnNode::Arm(arm)); self.ann.pre(self, AnnNode::Arm(arm));
self.ibox(0); self.ibox(0);
self.print_outer_attributes(&arm.attrs); self.print_outer_attributes(&self.attrs(arm.hir_id));
self.print_pat(&arm.pat); self.print_pat(&arm.pat);
self.s.space(); self.s.space();
if let Some(ref g) = arm.guard { if let Some(ref g) = arm.guard {

View file

@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
let (if_this_changed, then_this_would_need) = { let (if_this_changed, then_this_would_need) = {
let mut visitor = let mut visitor =
IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs); visitor.process_attrs(hir::CRATE_HIR_ID);
tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
(visitor.if_this_changed, visitor.then_this_would_need) (visitor.if_this_changed, visitor.then_this_would_need)
}; };
@ -113,9 +113,10 @@ impl IfThisChanged<'tcx> {
value value
} }
fn process_attrs(&mut self, hir_id: hir::HirId, attrs: &[ast::Attribute]) { fn process_attrs(&mut self, hir_id: hir::HirId) {
let def_id = self.tcx.hir().local_def_id(hir_id); let def_id = self.tcx.hir().local_def_id(hir_id);
let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id()); let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs { for attr in attrs {
if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) { if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) {
let dep_node_interned = self.argument(attr); let dep_node_interned = self.argument(attr);
@ -167,22 +168,22 @@ impl Visitor<'tcx> for IfThisChanged<'tcx> {
} }
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
self.process_attrs(item.hir_id(), &item.attrs); self.process_attrs(item.hir_id());
intravisit::walk_item(self, item); intravisit::walk_item(self, item);
} }
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
self.process_attrs(trait_item.hir_id(), &trait_item.attrs); self.process_attrs(trait_item.hir_id());
intravisit::walk_trait_item(self, trait_item); intravisit::walk_trait_item(self, trait_item);
} }
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
self.process_attrs(impl_item.hir_id(), &impl_item.attrs); self.process_attrs(impl_item.hir_id());
intravisit::walk_impl_item(self, impl_item); intravisit::walk_impl_item(self, impl_item);
} }
fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) { fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
self.process_attrs(s.hir_id, &s.attrs); self.process_attrs(s.hir_id);
intravisit::walk_struct_field(self, s); intravisit::walk_struct_field(self, s);
} }
} }

View file

@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
let ams = AssertModuleSource { tcx, available_cgus }; let ams = AssertModuleSource { tcx, available_cgus };
for attr in tcx.hir().krate().item.attrs { for attr in tcx.hir().attrs(rustc_hir::CRATE_HIR_ID) {
ams.check_attr(attr); ams.check_attr(attr);
} }
}) })

View file

@ -168,7 +168,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
// Note that we cannot use the existing "unused attribute"-infrastructure // Note that we cannot use the existing "unused attribute"-infrastructure
// here, since that is running before codegen. This is also the reason why // here, since that is running before codegen. This is also the reason why
// all codegen-specific attributes are `AssumedUsed` in rustc_ast::feature_gate. // all codegen-specific attributes are `AssumedUsed` in rustc_ast::feature_gate.
all_attrs.report_unchecked_attrs(&dirty_clean_visitor.checked_attrs); all_attrs.report_unchecked_attrs(dirty_clean_visitor.checked_attrs);
}) })
} }
@ -535,13 +535,14 @@ impl FindAllAttrs<'_, 'tcx> {
false false
} }
fn report_unchecked_attrs(&self, checked_attrs: &FxHashSet<ast::AttrId>) { fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet<ast::AttrId>) {
for attr in &self.found_attrs { for attr in &self.found_attrs {
if !checked_attrs.contains(&attr.id) { if !checked_attrs.contains(&attr.id) {
self.tcx.sess.span_err( self.tcx.sess.span_err(
attr.span, attr.span,
"found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute", "found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute",
); );
checked_attrs.insert(attr.id);
} }
} }
} }
@ -554,7 +555,7 @@ impl intravisit::Visitor<'tcx> for FindAllAttrs<'_, 'tcx> {
intravisit::NestedVisitorMap::All(self.tcx.hir()) intravisit::NestedVisitorMap::All(self.tcx.hir())
} }
fn visit_attribute(&mut self, attr: &'tcx Attribute) { fn visit_attribute(&mut self, _: hir::HirId, attr: &'tcx Attribute) {
if self.is_active_attr(attr) { if self.is_active_attr(attr) {
self.found_attrs.push(attr); self.found_attrs.push(attr);
} }

View file

@ -695,9 +695,7 @@ impl<I: Idx, T> IndexVec<I, T> {
pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> { pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
IndexVec { raw: self.raw, _marker: PhantomData } IndexVec { raw: self.raw, _marker: PhantomData }
} }
}
impl<I: Idx, T: Clone> IndexVec<I, T> {
/// Grows the index vector so that it contains an entry for /// Grows the index vector so that it contains an entry for
/// `elem`; if that is already true, then has no /// `elem`; if that is already true, then has no
/// effect. Otherwise, inserts new values as needed by invoking /// effect. Otherwise, inserts new values as needed by invoking
@ -710,11 +708,6 @@ impl<I: Idx, T: Clone> IndexVec<I, T> {
} }
} }
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
self.raw.resize(new_len, value)
}
#[inline] #[inline]
pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) { pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
let min_new_len = elem.index() + 1; let min_new_len = elem.index() + 1;
@ -722,6 +715,13 @@ impl<I: Idx, T: Clone> IndexVec<I, T> {
} }
} }
impl<I: Idx, T: Clone> IndexVec<I, T> {
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
self.raw.resize(new_len, value)
}
}
impl<I: Idx, T: Ord> IndexVec<I, T> { impl<I: Idx, T: Ord> IndexVec<I, T> {
#[inline] #[inline]
pub fn binary_search(&self, value: &T) -> Result<I, I> { pub fn binary_search(&self, value: &T) -> Result<I, I> {

View file

@ -25,7 +25,8 @@ struct Finder<'tcx> {
impl<'v> ItemLikeVisitor<'v> for Finder<'_> { impl<'v> ItemLikeVisitor<'v> for Finder<'_> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
if self.tcx.sess.contains_name(&item.attrs, sym::rustc_proc_macro_decls) { let attrs = self.tcx.hir().attrs(item.hir_id());
if self.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
self.decls = Some(item.hir_id()); self.decls = Some(item.hir_id());
} }
} }

View file

@ -508,8 +508,7 @@ impl MissingDoc {
fn check_missing_docs_attrs( fn check_missing_docs_attrs(
&self, &self,
cx: &LateContext<'_>, cx: &LateContext<'_>,
id: Option<hir::HirId>, id: hir::HirId,
attrs: &[ast::Attribute],
sp: Span, sp: Span,
article: &'static str, article: &'static str,
desc: &'static str, desc: &'static str,
@ -528,12 +527,13 @@ impl MissingDoc {
// Only check publicly-visible items, using the result from the privacy pass. // Only check publicly-visible items, using the result from the privacy pass.
// It's an option so the crate root can also use this function (it doesn't // It's an option so the crate root can also use this function (it doesn't
// have a `NodeId`). // have a `NodeId`).
if let Some(id) = id { if id != hir::CRATE_HIR_ID {
if !cx.access_levels.is_exported(id) { if !cx.access_levels.is_exported(id) {
return; return;
} }
} }
let attrs = cx.tcx.hir().attrs(id);
let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a)); let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
if !has_doc { if !has_doc {
cx.struct_span_lint( cx.struct_span_lint(
@ -565,10 +565,11 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
} }
fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) { fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "the", "crate"); self.check_missing_docs_attrs(cx, hir::CRATE_HIR_ID, krate.item.span, "the", "crate");
for macro_def in krate.exported_macros { for macro_def in krate.exported_macros {
let has_doc = macro_def.attrs.iter().any(|a| has_doc(cx.sess(), a)); let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
if !has_doc { if !has_doc {
cx.struct_span_lint( cx.struct_span_lint(
MISSING_DOCS, MISSING_DOCS,
@ -622,7 +623,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
self.check_missing_docs_attrs(cx, Some(it.hir_id()), &it.attrs, it.span, article, desc); self.check_missing_docs_attrs(cx, it.hir_id(), it.span, article, desc);
} }
fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
@ -632,14 +633,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
self.check_missing_docs_attrs( self.check_missing_docs_attrs(cx, trait_item.hir_id(), trait_item.span, article, desc);
cx,
Some(trait_item.hir_id()),
&trait_item.attrs,
trait_item.span,
article,
desc,
);
} }
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
@ -649,43 +643,22 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
} }
let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
self.check_missing_docs_attrs( self.check_missing_docs_attrs(cx, impl_item.hir_id(), impl_item.span, article, desc);
cx,
Some(impl_item.hir_id()),
&impl_item.attrs,
impl_item.span,
article,
desc,
);
} }
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) { fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id());
self.check_missing_docs_attrs( self.check_missing_docs_attrs(cx, foreign_item.hir_id(), foreign_item.span, article, desc);
cx,
Some(foreign_item.hir_id()),
&foreign_item.attrs,
foreign_item.span,
article,
desc,
);
} }
fn check_struct_field(&mut self, cx: &LateContext<'_>, sf: &hir::StructField<'_>) { fn check_struct_field(&mut self, cx: &LateContext<'_>, sf: &hir::StructField<'_>) {
if !sf.is_positional() { if !sf.is_positional() {
self.check_missing_docs_attrs( self.check_missing_docs_attrs(cx, sf.hir_id, sf.span, "a", "struct field")
cx,
Some(sf.hir_id),
&sf.attrs,
sf.span,
"a",
"struct field",
)
} }
} }
fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) { fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) {
self.check_missing_docs_attrs(cx, Some(v.id), &v.attrs, v.span, "a", "variant"); self.check_missing_docs_attrs(cx, v.id, v.span, "a", "variant");
} }
} }
@ -1119,9 +1092,10 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems { impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(it.hir_id());
match it.kind { match it.kind {
hir::ItemKind::Fn(.., ref generics, _) => { hir::ItemKind::Fn(.., ref generics, _) => {
if let Some(no_mangle_attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) { if let Some(no_mangle_attr) = cx.sess().find_by_name(attrs, sym::no_mangle) {
for param in generics.params { for param in generics.params {
match param.kind { match param.kind {
GenericParamKind::Lifetime { .. } => {} GenericParamKind::Lifetime { .. } => {}
@ -1147,7 +1121,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
} }
} }
hir::ItemKind::Const(..) => { hir::ItemKind::Const(..) => {
if cx.sess().contains_name(&it.attrs, sym::no_mangle) { if cx.sess().contains_name(attrs, sym::no_mangle) {
// Const items do not refer to a particular location in memory, and therefore // Const items do not refer to a particular location in memory, and therefore
// don't have anything to attach a symbol to // don't have anything to attach a symbol to
cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| { cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
@ -1827,7 +1801,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
return; return;
} }
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::rustc_test_marker) { let attrs = cx.tcx.hir().attrs(it.hir_id());
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| { cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
lint.build("cannot test inner items").emit() lint.build("cannot test inner items").emit()
}); });

View file

@ -283,7 +283,7 @@ fn is_doc_keyword(s: Symbol) -> bool {
impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
for attr in item.attrs { for attr in cx.tcx.hir().attrs(item.hir_id()) {
if !attr.has_name(sym::doc) { if !attr.has_name(sym::doc) {
continue; continue;
} }

View file

@ -16,7 +16,6 @@
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::walk_list;
use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
@ -53,10 +52,11 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
/// Merge the lints specified by any lint attributes into the /// Merge the lints specified by any lint attributes into the
/// current lint context, call the provided function, then reset the /// current lint context, call the provided function, then reset the
/// lints in effect to their previous state. /// lints in effect to their previous state.
fn with_lint_attrs<F>(&mut self, id: hir::HirId, attrs: &'tcx [ast::Attribute], f: F) fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F)
where where
F: FnOnce(&mut Self), F: FnOnce(&mut Self),
{ {
let attrs = self.context.tcx.hir().attrs(id);
let prev = self.context.last_node_with_lint_attrs; let prev = self.context.last_node_with_lint_attrs;
self.context.last_node_with_lint_attrs = id; self.context.last_node_with_lint_attrs = id;
self.enter_attrs(attrs); self.enter_attrs(attrs);
@ -125,7 +125,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
self.with_lint_attrs(param.hir_id, &param.attrs, |cx| { self.with_lint_attrs(param.hir_id, |cx| {
lint_callback!(cx, check_param, param); lint_callback!(cx, check_param, param);
hir_visit::walk_param(cx, param); hir_visit::walk_param(cx, param);
}); });
@ -142,7 +142,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
self.context.generics = it.kind.generics(); self.context.generics = it.kind.generics();
let old_cached_typeck_results = self.context.cached_typeck_results.take(); let old_cached_typeck_results = self.context.cached_typeck_results.take();
let old_enclosing_body = self.context.enclosing_body.take(); let old_enclosing_body = self.context.enclosing_body.take();
self.with_lint_attrs(it.hir_id(), &it.attrs, |cx| { self.with_lint_attrs(it.hir_id(), |cx| {
cx.with_param_env(it.hir_id(), |cx| { cx.with_param_env(it.hir_id(), |cx| {
lint_callback!(cx, check_item, it); lint_callback!(cx, check_item, it);
hir_visit::walk_item(cx, it); hir_visit::walk_item(cx, it);
@ -155,7 +155,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
self.with_lint_attrs(it.hir_id(), &it.attrs, |cx| { self.with_lint_attrs(it.hir_id(), |cx| {
cx.with_param_env(it.hir_id(), |cx| { cx.with_param_env(it.hir_id(), |cx| {
lint_callback!(cx, check_foreign_item, it); lint_callback!(cx, check_foreign_item, it);
hir_visit::walk_foreign_item(cx, it); hir_visit::walk_foreign_item(cx, it);
@ -170,7 +170,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
self.with_lint_attrs(e.hir_id, &e.attrs, |cx| { self.with_lint_attrs(e.hir_id, |cx| {
lint_callback!(cx, check_expr, e); lint_callback!(cx, check_expr, e);
hir_visit::walk_expr(cx, e); hir_visit::walk_expr(cx, e);
lint_callback!(cx, check_expr_post, e); lint_callback!(cx, check_expr_post, e);
@ -178,11 +178,9 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
let get_item = |id: hir::ItemId| self.context.tcx.hir().item(id);
let attrs = &s.kind.attrs(get_item);
// See `EarlyContextAndPass::visit_stmt` for an explanation // See `EarlyContextAndPass::visit_stmt` for an explanation
// of why we call `walk_stmt` outside of `with_lint_attrs` // of why we call `walk_stmt` outside of `with_lint_attrs`
self.with_lint_attrs(s.hir_id, attrs, |cx| { self.with_lint_attrs(s.hir_id, |cx| {
lint_callback!(cx, check_stmt, s); lint_callback!(cx, check_stmt, s);
}); });
hir_visit::walk_stmt(self, s); hir_visit::walk_stmt(self, s);
@ -222,7 +220,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) { fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
self.with_lint_attrs(s.hir_id, &s.attrs, |cx| { self.with_lint_attrs(s.hir_id, |cx| {
lint_callback!(cx, check_struct_field, s); lint_callback!(cx, check_struct_field, s);
hir_visit::walk_struct_field(cx, s); hir_visit::walk_struct_field(cx, s);
}) })
@ -234,7 +232,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
g: &'tcx hir::Generics<'tcx>, g: &'tcx hir::Generics<'tcx>,
item_id: hir::HirId, item_id: hir::HirId,
) { ) {
self.with_lint_attrs(v.id, &v.attrs, |cx| { self.with_lint_attrs(v.id, |cx| {
lint_callback!(cx, check_variant, v); lint_callback!(cx, check_variant, v);
hir_visit::walk_variant(cx, v, g, item_id); hir_visit::walk_variant(cx, v, g, item_id);
lint_callback!(cx, check_variant_post, v); lint_callback!(cx, check_variant_post, v);
@ -257,7 +255,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
} }
fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
self.with_lint_attrs(l.hir_id, &l.attrs, |cx| { self.with_lint_attrs(l.hir_id, |cx| {
lint_callback!(cx, check_local, l); lint_callback!(cx, check_local, l);
hir_visit::walk_local(cx, l); hir_visit::walk_local(cx, l);
}) })
@ -301,7 +299,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
let generics = self.context.generics.take(); let generics = self.context.generics.take();
self.context.generics = Some(&trait_item.generics); self.context.generics = Some(&trait_item.generics);
self.with_lint_attrs(trait_item.hir_id(), &trait_item.attrs, |cx| { self.with_lint_attrs(trait_item.hir_id(), |cx| {
cx.with_param_env(trait_item.hir_id(), |cx| { cx.with_param_env(trait_item.hir_id(), |cx| {
lint_callback!(cx, check_trait_item, trait_item); lint_callback!(cx, check_trait_item, trait_item);
hir_visit::walk_trait_item(cx, trait_item); hir_visit::walk_trait_item(cx, trait_item);
@ -314,7 +312,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
let generics = self.context.generics.take(); let generics = self.context.generics.take();
self.context.generics = Some(&impl_item.generics); self.context.generics = Some(&impl_item.generics);
self.with_lint_attrs(impl_item.hir_id(), &impl_item.attrs, |cx| { self.with_lint_attrs(impl_item.hir_id(), |cx| {
cx.with_param_env(impl_item.hir_id(), |cx| { cx.with_param_env(impl_item.hir_id(), |cx| {
lint_callback!(cx, check_impl_item, impl_item); lint_callback!(cx, check_impl_item, impl_item);
hir_visit::walk_impl_item(cx, impl_item); hir_visit::walk_impl_item(cx, impl_item);
@ -334,8 +332,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
hir_visit::walk_path(self, p); hir_visit::walk_path(self, p);
} }
fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) { fn visit_attribute(&mut self, hir_id: hir::HirId, attr: &'tcx ast::Attribute) {
lint_callback!(self, check_attribute, attr); self.with_lint_attrs(hir_id, |cx| {
lint_callback!(cx, check_attribute, attr);
})
} }
} }
@ -396,7 +396,9 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
// Visit the crate attributes // Visit the crate attributes
if hir_id == hir::CRATE_HIR_ID { if hir_id == hir::CRATE_HIR_ID {
walk_list!(cx, visit_attribute, tcx.hir().attrs(hir::CRATE_HIR_ID)); for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
cx.visit_attribute(hir_id, attr)
}
} }
} }
@ -440,7 +442,7 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
let mut cx = LateContextAndPass { context, pass }; let mut cx = LateContextAndPass { context, pass };
// Visit the whole crate. // Visit the whole crate.
cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| { cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| {
// since the root module isn't visited as an item (because it isn't an // since the root module isn't visited as an item (because it isn't an
// item), warn for it here. // item), warn for it here.
lint_callback!(cx, check_crate, krate); lint_callback!(cx, check_crate, krate);

View file

@ -38,7 +38,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
builder.levels.id_to_set.reserve(krate.exported_macros.len() + 1); builder.levels.id_to_set.reserve(krate.exported_macros.len() + 1);
let push = builder.levels.push(&krate.item.attrs, &store, true); let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
builder.levels.register_id(hir::CRATE_HIR_ID); builder.levels.register_id(hir::CRATE_HIR_ID);
for macro_def in krate.exported_macros { for macro_def in krate.exported_macros {
builder.levels.register_id(macro_def.hir_id()); builder.levels.register_id(macro_def.hir_id());
@ -566,11 +566,12 @@ struct LintLevelMapBuilder<'a, 'tcx> {
} }
impl LintLevelMapBuilder<'_, '_> { impl LintLevelMapBuilder<'_, '_> {
fn with_lint_attrs<F>(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F) fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F)
where where
F: FnOnce(&mut Self), F: FnOnce(&mut Self),
{ {
let is_crate_hir = id == hir::CRATE_HIR_ID; let is_crate_hir = id == hir::CRATE_HIR_ID;
let attrs = self.tcx.hir().attrs(id);
let push = self.levels.push(attrs, self.store, is_crate_hir); let push = self.levels.push(attrs, self.store, is_crate_hir);
if push.changed { if push.changed {
self.levels.register_id(id); self.levels.register_id(id);
@ -588,19 +589,19 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
} }
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
self.with_lint_attrs(param.hir_id, &param.attrs, |builder| { self.with_lint_attrs(param.hir_id, |builder| {
intravisit::walk_param(builder, param); intravisit::walk_param(builder, param);
}); });
} }
fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
self.with_lint_attrs(it.hir_id(), &it.attrs, |builder| { self.with_lint_attrs(it.hir_id(), |builder| {
intravisit::walk_item(builder, it); intravisit::walk_item(builder, it);
}); });
} }
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
self.with_lint_attrs(it.hir_id(), &it.attrs, |builder| { self.with_lint_attrs(it.hir_id(), |builder| {
intravisit::walk_foreign_item(builder, it); intravisit::walk_foreign_item(builder, it);
}) })
} }
@ -613,13 +614,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
} }
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
self.with_lint_attrs(e.hir_id, &e.attrs, |builder| { self.with_lint_attrs(e.hir_id, |builder| {
intravisit::walk_expr(builder, e); intravisit::walk_expr(builder, e);
}) })
} }
fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) { fn visit_struct_field(&mut self, s: &'tcx hir::StructField<'tcx>) {
self.with_lint_attrs(s.hir_id, &s.attrs, |builder| { self.with_lint_attrs(s.hir_id, |builder| {
intravisit::walk_struct_field(builder, s); intravisit::walk_struct_field(builder, s);
}) })
} }
@ -630,31 +631,31 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
g: &'tcx hir::Generics<'tcx>, g: &'tcx hir::Generics<'tcx>,
item_id: hir::HirId, item_id: hir::HirId,
) { ) {
self.with_lint_attrs(v.id, &v.attrs, |builder| { self.with_lint_attrs(v.id, |builder| {
intravisit::walk_variant(builder, v, g, item_id); intravisit::walk_variant(builder, v, g, item_id);
}) })
} }
fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) { fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
self.with_lint_attrs(l.hir_id, &l.attrs, |builder| { self.with_lint_attrs(l.hir_id, |builder| {
intravisit::walk_local(builder, l); intravisit::walk_local(builder, l);
}) })
} }
fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
self.with_lint_attrs(a.hir_id, &a.attrs, |builder| { self.with_lint_attrs(a.hir_id, |builder| {
intravisit::walk_arm(builder, a); intravisit::walk_arm(builder, a);
}) })
} }
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
self.with_lint_attrs(trait_item.hir_id(), &trait_item.attrs, |builder| { self.with_lint_attrs(trait_item.hir_id(), |builder| {
intravisit::walk_trait_item(builder, trait_item); intravisit::walk_trait_item(builder, trait_item);
}); });
} }
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
self.with_lint_attrs(impl_item.hir_id(), &impl_item.attrs, |builder| { self.with_lint_attrs(impl_item.hir_id(), |builder| {
intravisit::walk_impl_item(builder, impl_item); intravisit::walk_impl_item(builder, impl_item);
}); });
} }

View file

@ -400,14 +400,15 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
} }
_ => (), _ => (),
}, },
FnKind::ItemFn(ident, _, header, _, attrs) => { FnKind::ItemFn(ident, _, header, _) => {
let attrs = cx.tcx.hir().attrs(id);
// Skip foreign-ABI #[no_mangle] functions (Issue #31924) // Skip foreign-ABI #[no_mangle] functions (Issue #31924)
if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) { if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
return; return;
} }
self.check_snake_case(cx, "function", ident); self.check_snake_case(cx, "function", ident);
} }
FnKind::Closure(_) => (), FnKind::Closure => (),
} }
} }
@ -504,8 +505,9 @@ impl NonUpperCaseGlobals {
impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(it.hir_id());
match it.kind { match it.kind {
hir::ItemKind::Static(..) if !cx.sess().contains_name(&it.attrs, sym::no_mangle) => { hir::ItemKind::Static(..) if !cx.sess().contains_name(attrs, sym::no_mangle) => {
NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident);
} }
hir::ItemKind::Const(..) => { hir::ItemKind::Const(..) => {

View file

@ -406,6 +406,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAttributes {
if !cx.sess().is_attr_used(attr) { if !cx.sess().is_attr_used(attr) {
debug!("emitting warning for: {:?}", attr); debug!("emitting warning for: {:?}", attr);
cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| {
// Mark as used to avoid duplicate warnings.
cx.sess().mark_attr_used(attr);
lint.build("unused attribute").emit() lint.build("unused attribute").emit()
}); });
// Is it a builtin attribute that must be used at the crate level? // Is it a builtin attribute that must be used at the crate level?

View file

@ -8,7 +8,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
let mut collector = Collector { tcx, args: Vec::new() }; let mut collector = Collector { tcx, args: Vec::new() };
tcx.hir().krate().visit_all_item_likes(&mut collector); tcx.hir().krate().visit_all_item_likes(&mut collector);
for attr in tcx.hir().krate().item.attrs.iter() { for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
if attr.has_name(sym::link_args) { if attr.has_name(sym::link_args) {
if let Some(linkarg) = attr.value_str() { if let Some(linkarg) = attr.value_str() {
collector.add_link_args(linkarg); collector.add_link_args(linkarg);
@ -36,7 +36,9 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> {
// First, add all of the custom #[link_args] attributes // First, add all of the custom #[link_args] attributes
let sess = &self.tcx.sess; let sess = &self.tcx.sess;
for m in it.attrs.iter().filter(|a| sess.check_name(a, sym::link_args)) { for m in
self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link_args))
{
if let Some(linkarg) = m.value_str() { if let Some(linkarg) = m.value_str() {
self.add_link_args(linkarg); self.add_link_args(linkarg);
} }

View file

@ -44,7 +44,8 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
// Process all of the #[link(..)]-style arguments // Process all of the #[link(..)]-style arguments
let sess = &self.tcx.sess; let sess = &self.tcx.sess;
for m in it.attrs.iter().filter(|a| sess.check_name(a, sym::link)) { for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link))
{
let items = match m.meta_item_list() { let items = match m.meta_item_list() {
Some(item) => item, Some(item) => item,
None => continue, None => continue,

View file

@ -12,7 +12,6 @@
//! for the `Code` associated with a particular NodeId. //! for the `Code` associated with a particular NodeId.
use crate::hir::map::Map; use crate::hir::map::Map;
use rustc_ast::Attribute;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{Expr, FnDecl, Node}; use rustc_hir::{Expr, FnDecl, Node};
@ -105,7 +104,6 @@ struct ItemFnParts<'a> {
body: hir::BodyId, body: hir::BodyId,
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
attrs: &'a [Attribute],
} }
/// These are all the components one can extract from a closure expr /// These are all the components one can extract from a closure expr
@ -115,18 +113,11 @@ struct ClosureParts<'a> {
body: hir::BodyId, body: hir::BodyId,
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
attrs: &'a [Attribute],
} }
impl<'a> ClosureParts<'a> { impl<'a> ClosureParts<'a> {
fn new( fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self {
d: &'a FnDecl<'a>, ClosureParts { decl: d, body: b, id, span: s }
b: hir::BodyId,
id: hir::HirId,
s: Span,
attrs: &'a [Attribute],
) -> Self {
ClosureParts { decl: d, body: b, id, span: s, attrs }
} }
} }
@ -146,7 +137,7 @@ impl<'a> FnLikeNode<'a> {
pub fn body(self) -> hir::BodyId { pub fn body(self) -> hir::BodyId {
self.handle( self.handle(
|i: ItemFnParts<'a>| i.body, |i: ItemFnParts<'a>| i.body,
|_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _, _| body, |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body,
|c: ClosureParts<'a>| c.body, |c: ClosureParts<'a>| c.body,
) )
} }
@ -154,7 +145,7 @@ impl<'a> FnLikeNode<'a> {
pub fn decl(self) -> &'a FnDecl<'a> { pub fn decl(self) -> &'a FnDecl<'a> {
self.handle( self.handle(
|i: ItemFnParts<'a>| &*i.decl, |i: ItemFnParts<'a>| &*i.decl,
|_, _, sig: &'a hir::FnSig<'a>, _, _, _, _| &sig.decl, |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl,
|c: ClosureParts<'a>| c.decl, |c: ClosureParts<'a>| c.decl,
) )
} }
@ -162,7 +153,7 @@ impl<'a> FnLikeNode<'a> {
pub fn span(self) -> Span { pub fn span(self) -> Span {
self.handle( self.handle(
|i: ItemFnParts<'_>| i.span, |i: ItemFnParts<'_>| i.span,
|_, _, _: &'a hir::FnSig<'a>, _, _, span, _| span, |_, _, _: &'a hir::FnSig<'a>, _, _, span| span,
|c: ClosureParts<'_>| c.span, |c: ClosureParts<'_>| c.span,
) )
} }
@ -170,7 +161,7 @@ impl<'a> FnLikeNode<'a> {
pub fn id(self) -> hir::HirId { pub fn id(self) -> hir::HirId {
self.handle( self.handle(
|i: ItemFnParts<'_>| i.id, |i: ItemFnParts<'_>| i.id,
|id, _, _: &'a hir::FnSig<'a>, _, _, _, _| id, |id, _, _: &'a hir::FnSig<'a>, _, _, _| id,
|c: ClosureParts<'_>| c.id, |c: ClosureParts<'_>| c.id,
) )
} }
@ -189,12 +180,11 @@ impl<'a> FnLikeNode<'a> {
pub fn kind(self) -> FnKind<'a> { pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> { let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs) FnKind::ItemFn(p.ident, p.generics, p.header, p.vis)
};
let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs);
let method = |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _, attrs| {
FnKind::Method(ident, sig, vis, attrs)
}; };
let closure = |_: ClosureParts<'a>| FnKind::Closure;
let method =
|_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis);
self.handle(item, method, closure) self.handle(item, method, closure)
} }
@ -208,7 +198,6 @@ impl<'a> FnLikeNode<'a> {
Option<&'a hir::Visibility<'a>>, Option<&'a hir::Visibility<'a>>,
hir::BodyId, hir::BodyId,
Span, Span,
&'a [Attribute],
) -> A, ) -> A,
C: FnOnce(ClosureParts<'a>) -> A, C: FnOnce(ClosureParts<'a>) -> A,
{ {
@ -221,7 +210,6 @@ impl<'a> FnLikeNode<'a> {
body: block, body: block,
vis: &i.vis, vis: &i.vis,
span: i.span, span: i.span,
attrs: &i.attrs,
header: sig.header, header: sig.header,
generics, generics,
}), }),
@ -229,19 +217,19 @@ impl<'a> FnLikeNode<'a> {
}, },
Node::TraitItem(ti) => match ti.kind { Node::TraitItem(ti) => match ti.kind {
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
method(ti.hir_id(), ti.ident, sig, None, body, ti.span, &ti.attrs) method(ti.hir_id(), ti.ident, sig, None, body, ti.span)
} }
_ => bug!("trait method FnLikeNode that is not fn-like"), _ => bug!("trait method FnLikeNode that is not fn-like"),
}, },
Node::ImplItem(ii) => match ii.kind { Node::ImplItem(ii) => match ii.kind {
hir::ImplItemKind::Fn(ref sig, body) => { hir::ImplItemKind::Fn(ref sig, body) => {
method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span)
} }
_ => bug!("impl method FnLikeNode that is not fn-like"), _ => bug!("impl method FnLikeNode that is not fn-like"),
}, },
Node::Expr(e) => match e.kind { Node::Expr(e) => match e.kind {
hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)) closure(ClosureParts::new(&decl, block, e.hir_id, e.span))
} }
_ => bug!("expr FnLikeNode that is not fn-like"), _ => bug!("expr FnLikeNode that is not fn-like"),
}, },

View file

@ -116,6 +116,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
modules: _, modules: _,
proc_macros: _, proc_macros: _,
trait_map: _, trait_map: _,
attrs: _,
} = *krate; } = *krate;
hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)

View file

@ -457,10 +457,7 @@ impl<'hir> Map<'hir> {
/// invoking `krate.attrs` because it registers a tighter /// invoking `krate.attrs` because it registers a tighter
/// dep-graph access. /// dep-graph access.
pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
match self.get_entry(CRATE_HIR_ID).node { self.attrs(CRATE_HIR_ID)
Node::Crate(item) => item.attrs,
_ => bug!(),
}
} }
pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
@ -853,34 +850,7 @@ impl<'hir> Map<'hir> {
/// Given a node ID, gets a list of attributes associated with the AST /// Given a node ID, gets a list of attributes associated with the AST
/// corresponding to the node-ID. /// corresponding to the node-ID.
pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
self.find_entry(id).map_or(&[], |entry| match entry.node { self.tcx.hir_attrs(id.owner).get(id.local_id)
Node::Param(a) => a.attrs,
Node::Local(l) => &l.attrs[..],
Node::Item(i) => i.attrs,
Node::ForeignItem(fi) => fi.attrs,
Node::TraitItem(ref ti) => ti.attrs,
Node::ImplItem(ref ii) => ii.attrs,
Node::Variant(ref v) => v.attrs,
Node::Field(ref f) => f.attrs,
Node::Expr(ref e) => &*e.attrs,
Node::Stmt(ref s) => s.kind.attrs(|id| self.item(id)),
Node::Arm(ref a) => &*a.attrs,
Node::GenericParam(param) => param.attrs,
// Unit/tuple structs/variants take the attributes straight from
// the struct/variant definition.
Node::Ctor(..) => self.attrs(self.get_parent_item(id)),
Node::Crate(item) => item.attrs,
Node::MacroDef(def) => def.attrs,
Node::AnonConst(..)
| Node::PathSegment(..)
| Node::Ty(..)
| Node::Pat(..)
| Node::Binding(..)
| Node::TraitRef(..)
| Node::Block(..)
| Node::Lifetime(..)
| Node::Visibility(..) => &[],
})
} }
/// Gets the span of the definition of the specified HIR node. /// Gets the span of the definition of the specified HIR node.

View file

@ -9,6 +9,7 @@ pub mod place;
use crate::ich::StableHashingContext; use crate::ich::StableHashingContext;
use crate::ty::query::Providers; use crate::ty::query::Providers;
use crate::ty::TyCtxt; use crate::ty::TyCtxt;
use rustc_ast::Attribute;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@ -16,6 +17,7 @@ use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::*; use rustc_hir::*;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use std::collections::BTreeMap;
#[derive(Debug)] #[derive(Debug)]
pub struct Owner<'tcx> { pub struct Owner<'tcx> {
@ -55,6 +57,48 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OwnerNodes<'tcx> {
} }
} }
#[derive(Copy, Clone)]
pub struct AttributeMap<'tcx> {
map: &'tcx BTreeMap<HirId, &'tcx [Attribute]>,
prefix: LocalDefId,
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for AttributeMap<'tcx> {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let range = self.range();
range.clone().count().hash_stable(hcx, hasher);
for (key, value) in range {
key.hash_stable(hcx, hasher);
value.hash_stable(hcx, hasher);
}
}
}
impl<'tcx> std::fmt::Debug for AttributeMap<'tcx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AttributeMap")
.field("prefix", &self.prefix)
.field("range", &&self.range().collect::<Vec<_>>()[..])
.finish()
}
}
impl<'tcx> AttributeMap<'tcx> {
fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
self.map.get(&HirId { owner: self.prefix, local_id: id }).copied().unwrap_or(&[])
}
fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[Attribute]> {
let local_zero = ItemLocalId::from_u32(0);
let range = HirId { owner: self.prefix, local_id: local_zero }..HirId {
owner: LocalDefId { local_def_index: self.prefix.local_def_index + 1 },
local_id: local_zero,
};
self.map.range(range)
}
}
impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxt<'tcx> {
#[inline(always)] #[inline(always)]
pub fn hir(self) -> map::Map<'tcx> { pub fn hir(self) -> map::Map<'tcx> {
@ -76,6 +120,7 @@ pub fn provide(providers: &mut Providers) {
providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id]; providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref(); providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
providers.fn_arg_names = |tcx, id| { providers.fn_arg_names = |tcx, id| {
let hir = tcx.hir(); let hir = tcx.hir();

View file

@ -66,11 +66,10 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {
fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) {
self.while_hashing_hir_bodies(true, |hcx| { self.while_hashing_hir_bodies(true, |hcx| {
let hir::Expr { hir_id: _, ref span, ref kind, ref attrs } = *expr; let hir::Expr { hir_id: _, ref span, ref kind } = *expr;
span.hash_stable(hcx, hasher); span.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher); kind.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
}) })
} }

View file

@ -61,6 +61,15 @@ rustc_queries! {
desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
} }
/// Gives access to the HIR attributes inside the HIR owner `key`.
///
/// This can be conveniently accessed by methods on `tcx.hir()`.
/// Avoid calling this query directly.
query hir_attrs(key: LocalDefId) -> rustc_middle::hir::AttributeMap<'tcx> {
eval_always
desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Computes the `DefId` of the corresponding const parameter in case the `key` is a /// Computes the `DefId` of the corresponding const parameter in case the `key` is a
/// const argument and returns `None` otherwise. /// const argument and returns `None` otherwise.
/// ///

View file

@ -15,7 +15,7 @@ crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) { if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
if let FnKind::Closure(_) = fn_like_node.kind() { if let FnKind::Closure = fn_like_node.kind() {
// closures can't recur, so they don't matter. // closures can't recur, so they don't matter.
return; return;
} }

View file

@ -62,12 +62,12 @@ impl CheckAttrVisitor<'tcx> {
fn check_attributes( fn check_attributes(
&self, &self,
hir_id: HirId, hir_id: HirId,
attrs: &'hir [Attribute],
span: &Span, span: &Span,
target: Target, target: Target,
item: Option<ItemLike<'_>>, item: Option<ItemLike<'_>>,
) { ) {
let mut is_valid = true; let mut is_valid = true;
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs { for attr in attrs {
is_valid &= if self.tcx.sess.check_name(attr, sym::inline) { is_valid &= if self.tcx.sess.check_name(attr, sym::inline) {
self.check_inline(hir_id, attr, span, target) self.check_inline(hir_id, attr, span, target)
@ -1213,53 +1213,29 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
fn visit_item(&mut self, item: &'tcx Item<'tcx>) { fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
let target = Target::from_item(item); let target = Target::from_item(item);
self.check_attributes( self.check_attributes(item.hir_id(), &item.span, target, Some(ItemLike::Item(item)));
item.hir_id(),
item.attrs,
&item.span,
target,
Some(ItemLike::Item(item)),
);
intravisit::walk_item(self, item) intravisit::walk_item(self, item)
} }
fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) { fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
let target = Target::from_generic_param(generic_param); let target = Target::from_generic_param(generic_param);
self.check_attributes( self.check_attributes(generic_param.hir_id, &generic_param.span, target, None);
generic_param.hir_id,
generic_param.attrs,
&generic_param.span,
target,
None,
);
intravisit::walk_generic_param(self, generic_param) intravisit::walk_generic_param(self, generic_param)
} }
fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) { fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
let target = Target::from_trait_item(trait_item); let target = Target::from_trait_item(trait_item);
self.check_attributes( self.check_attributes(trait_item.hir_id(), &trait_item.span, target, None);
trait_item.hir_id(),
&trait_item.attrs,
&trait_item.span,
target,
None,
);
intravisit::walk_trait_item(self, trait_item) intravisit::walk_trait_item(self, trait_item)
} }
fn visit_struct_field(&mut self, struct_field: &'tcx hir::StructField<'tcx>) { fn visit_struct_field(&mut self, struct_field: &'tcx hir::StructField<'tcx>) {
self.check_attributes( self.check_attributes(struct_field.hir_id, &struct_field.span, Target::Field, None);
struct_field.hir_id,
&struct_field.attrs,
&struct_field.span,
Target::Field,
None,
);
intravisit::walk_struct_field(self, struct_field); intravisit::walk_struct_field(self, struct_field);
} }
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
self.check_attributes(arm.hir_id, &arm.attrs, &arm.span, Target::Arm, None); self.check_attributes(arm.hir_id, &arm.span, Target::Arm, None);
intravisit::walk_arm(self, arm); intravisit::walk_arm(self, arm);
} }
@ -1267,7 +1243,6 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
let target = Target::from_foreign_item(f_item); let target = Target::from_foreign_item(f_item);
self.check_attributes( self.check_attributes(
f_item.hir_id(), f_item.hir_id(),
&f_item.attrs,
&f_item.span, &f_item.span,
target, target,
Some(ItemLike::ForeignItem(f_item)), Some(ItemLike::ForeignItem(f_item)),
@ -1277,14 +1252,14 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
let target = target_from_impl_item(self.tcx, impl_item); 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); self.check_attributes(impl_item.hir_id(), &impl_item.span, target, None);
intravisit::walk_impl_item(self, impl_item) intravisit::walk_impl_item(self, impl_item)
} }
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
// When checking statements ignore expressions, they will be checked later. // When checking statements ignore expressions, they will be checked later.
if let hir::StmtKind::Local(ref l) = stmt.kind { if let hir::StmtKind::Local(ref l) = stmt.kind {
self.check_attributes(l.hir_id, &l.attrs, &stmt.span, Target::Statement, None); self.check_attributes(l.hir_id, &stmt.span, Target::Statement, None);
} }
intravisit::walk_stmt(self, stmt) intravisit::walk_stmt(self, stmt)
} }
@ -1295,7 +1270,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
_ => Target::Expression, _ => Target::Expression,
}; };
self.check_attributes(expr.hir_id, &expr.attrs, &expr.span, target, None); self.check_attributes(expr.hir_id, &expr.span, target, None);
intravisit::walk_expr(self, expr) intravisit::walk_expr(self, expr)
} }
@ -1305,23 +1280,17 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
generics: &'tcx hir::Generics<'tcx>, generics: &'tcx hir::Generics<'tcx>,
item_id: HirId, item_id: HirId,
) { ) {
self.check_attributes(variant.id, variant.attrs, &variant.span, Target::Variant, None); self.check_attributes(variant.id, &variant.span, Target::Variant, None);
intravisit::walk_variant(self, variant, generics, item_id) intravisit::walk_variant(self, variant, generics, item_id)
} }
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) { fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
self.check_attributes( self.check_attributes(macro_def.hir_id(), &macro_def.span, Target::MacroDef, None);
macro_def.hir_id(),
macro_def.attrs,
&macro_def.span,
Target::MacroDef,
None,
);
intravisit::walk_macro_def(self, macro_def); intravisit::walk_macro_def(self, macro_def);
} }
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
self.check_attributes(param.hir_id, param.attrs, &param.span, Target::Param, None); self.check_attributes(param.hir_id, &param.span, Target::Param, None);
intravisit::walk_param(self, param); intravisit::walk_param(self, param);
} }
@ -1389,13 +1358,7 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
tcx.hir().visit_exported_macros_in_krate(check_attr_visitor); tcx.hir().visit_exported_macros_in_krate(check_attr_visitor);
check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs); check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs);
if module_def_id.is_top_level_module() { if module_def_id.is_top_level_module() {
check_attr_visitor.check_attributes( check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None);
CRATE_HIR_ID,
tcx.hir().krate_attrs(),
&DUMMY_SP,
Target::Mod,
None,
);
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs()); check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
} }
} }

View file

@ -15,7 +15,6 @@ use rustc_middle::middle::privacy;
use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::lint; use rustc_session::lint;
use rustc_ast as ast;
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
// Any local node that may call something in its body block should be // Any local node that may call something in its body block should be
@ -346,11 +345,8 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
} }
} }
fn has_allow_dead_code_or_lang_attr( fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
tcx: TyCtxt<'_>, let attrs = tcx.hir().attrs(id);
id: hir::HirId,
attrs: &[ast::Attribute],
) -> bool {
if tcx.sess.contains_name(attrs, sym::lang) { if tcx.sess.contains_name(attrs, sym::lang) {
return true; return true;
} }
@ -400,8 +396,7 @@ struct LifeSeeder<'k, 'tcx> {
impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
let allow_dead_code = let allow_dead_code = has_allow_dead_code_or_lang_attr(self.tcx, item.hir_id());
has_allow_dead_code_or_lang_attr(self.tcx, item.hir_id(), &item.attrs);
if allow_dead_code { if allow_dead_code {
self.worklist.push(item.hir_id()); self.worklist.push(item.hir_id());
} }
@ -424,11 +419,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
for impl_item_ref in items { for impl_item_ref in items {
let impl_item = self.krate.impl_item(impl_item_ref.id); let impl_item = self.krate.impl_item(impl_item_ref.id);
if of_trait.is_some() if of_trait.is_some()
|| has_allow_dead_code_or_lang_attr( || has_allow_dead_code_or_lang_attr(self.tcx, impl_item.hir_id())
self.tcx,
impl_item.hir_id(),
&impl_item.attrs,
)
{ {
self.worklist.push(impl_item_ref.id.hir_id()); self.worklist.push(impl_item_ref.id.hir_id());
} }
@ -446,7 +437,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
use hir::TraitItemKind::{Const, Fn}; use hir::TraitItemKind::{Const, Fn};
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
&& has_allow_dead_code_or_lang_attr(self.tcx, trait_item.hir_id(), &trait_item.attrs) && has_allow_dead_code_or_lang_attr(self.tcx, trait_item.hir_id())
{ {
self.worklist.push(trait_item.hir_id()); self.worklist.push(trait_item.hir_id());
} }
@ -459,11 +450,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) { fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
use hir::ForeignItemKind::{Fn, Static}; use hir::ForeignItemKind::{Fn, Static};
if matches!(foreign_item.kind, Static(..) | Fn(..)) if matches!(foreign_item.kind, Static(..) | Fn(..))
&& has_allow_dead_code_or_lang_attr( && has_allow_dead_code_or_lang_attr(self.tcx, foreign_item.hir_id())
self.tcx,
foreign_item.hir_id(),
&foreign_item.attrs,
)
{ {
self.worklist.push(foreign_item.hir_id()); self.worklist.push(foreign_item.hir_id());
} }
@ -543,17 +530,16 @@ impl DeadVisitor<'tcx> {
!field.is_positional() !field.is_positional()
&& !self.symbol_is_live(field.hir_id) && !self.symbol_is_live(field.hir_id)
&& !field_type.is_phantom_data() && !field_type.is_phantom_data()
&& !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs) && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id)
} }
fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool { fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool {
!self.symbol_is_live(variant.id) !self.symbol_is_live(variant.id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id)
&& !has_allow_dead_code_or_lang_attr(self.tcx, variant.id, &variant.attrs)
} }
fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool { fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool {
!self.symbol_is_live(fi.hir_id()) !self.symbol_is_live(fi.hir_id())
&& !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id(), &fi.attrs) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id())
} }
// id := HIR id of an item's definition. // id := HIR id of an item's definition.

View file

@ -27,19 +27,19 @@ struct DiagnosticItemCollector<'tcx> {
impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> { impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
self.observe_item(&item.attrs, item.def_id); self.observe_item(item.def_id);
} }
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
self.observe_item(&trait_item.attrs, trait_item.def_id); self.observe_item(trait_item.def_id);
} }
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
self.observe_item(&impl_item.attrs, impl_item.def_id); self.observe_item(impl_item.def_id);
} }
fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) { fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
self.observe_item(foreign_item.attrs, foreign_item.def_id); self.observe_item(foreign_item.def_id);
} }
} }
@ -48,7 +48,9 @@ impl<'tcx> DiagnosticItemCollector<'tcx> {
DiagnosticItemCollector { tcx, items: Default::default() } DiagnosticItemCollector { tcx, items: Default::default() }
} }
fn observe_item(&mut self, attrs: &[ast::Attribute], def_id: LocalDefId) { fn observe_item(&mut self, def_id: LocalDefId) {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let attrs = self.tcx.hir().attrs(hir_id);
if let Some(name) = extract(&self.tcx.sess, attrs) { if let Some(name) = extract(&self.tcx.sess, attrs) {
// insert into our table // insert into our table
collect_item(self.tcx, &mut self.items, name, def_id.to_def_id()); collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
@ -105,7 +107,7 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
tcx.hir().krate().visit_all_item_likes(&mut collector); tcx.hir().krate().visit_all_item_likes(&mut collector);
for m in tcx.hir().krate().exported_macros { for m in tcx.hir().krate().exported_macros {
collector.observe_item(m.attrs, m.def_id); collector.observe_item(m.def_id);
} }
collector.items collector.items

View file

@ -2,7 +2,7 @@ use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem}; use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
@ -60,7 +60,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
} }
// If the user wants no main function at all, then stop here. // If the user wants no main function at all, then stop here.
if tcx.sess.contains_name(&tcx.hir().krate().item.attrs, sym::no_main) { if tcx.sess.contains_name(&tcx.hir().attrs(CRATE_HIR_ID), sym::no_main) {
return None; return None;
} }
@ -80,10 +80,11 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs` // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
// (with `ast::Item`), so make sure to keep them in sync. // (with `ast::Item`), so make sure to keep them in sync.
fn entry_point_type(sess: &Session, item: &Item<'_>, at_root: bool) -> EntryPointType { fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool) -> EntryPointType {
if sess.contains_name(&item.attrs, sym::start) { let attrs = ctxt.map.attrs(item.hir_id());
if ctxt.session.contains_name(attrs, sym::start) {
EntryPointType::Start EntryPointType::Start
} else if sess.contains_name(&item.attrs, sym::main) { } else if ctxt.session.contains_name(attrs, sym::main) {
EntryPointType::MainAttr EntryPointType::MainAttr
} else if item.ident.name == sym::main { } else if item.ident.name == sym::main {
if at_root { if at_root {
@ -103,13 +104,14 @@ fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
} }
fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
match entry_point_type(&ctxt.session, item, at_root) { match entry_point_type(ctxt, item, at_root) {
EntryPointType::None => (), EntryPointType::None => (),
_ if !matches!(item.kind, ItemKind::Fn(..)) => { _ if !matches!(item.kind, ItemKind::Fn(..)) => {
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::start) { let attrs = ctxt.map.attrs(item.hir_id());
if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) {
throw_attr_err(&ctxt.session, attr.span, "start"); throw_attr_err(&ctxt.session, attr.span, "start");
} }
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::main) { if let Some(attr) = ctxt.session.find_by_name(attrs, sym::main) {
throw_attr_err(&ctxt.session, attr.span, "main"); throw_attr_err(&ctxt.session, attr.span, "main");
} }
} }

View file

@ -241,7 +241,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_assoc_type_binding(self, type_binding) hir_visit::walk_assoc_type_binding(self, type_binding)
} }
fn visit_attribute(&mut self, attr: &'v ast::Attribute) { fn visit_attribute(&mut self, _: hir::HirId, attr: &'v ast::Attribute) {
self.record("Attribute", Id::Attr(attr.id), attr); self.record("Attribute", Id::Attr(attr.id), attr);
} }

View file

@ -13,7 +13,6 @@ use crate::weak_lang_items;
use rustc_middle::middle::cstore::ExternCrate; use rustc_middle::middle::cstore::ExternCrate;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_ast::Attribute;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@ -30,29 +29,21 @@ struct LanguageItemCollector<'tcx> {
impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
self.check_for_lang(Target::from_item(item), item.hir_id(), item.attrs); self.check_for_lang(Target::from_item(item), item.hir_id());
if let hir::ItemKind::Enum(def, ..) = &item.kind { if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants { for variant in def.variants {
self.check_for_lang(Target::Variant, variant.id, variant.attrs); self.check_for_lang(Target::Variant, variant.id);
} }
} }
} }
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
self.check_for_lang( self.check_for_lang(Target::from_trait_item(trait_item), trait_item.hir_id())
Target::from_trait_item(trait_item),
trait_item.hir_id(),
trait_item.attrs,
)
} }
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
self.check_for_lang( self.check_for_lang(target_from_impl_item(self.tcx, impl_item), impl_item.hir_id())
target_from_impl_item(self.tcx, impl_item),
impl_item.hir_id(),
impl_item.attrs,
)
} }
fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {} fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {}
@ -63,7 +54,8 @@ impl LanguageItemCollector<'tcx> {
LanguageItemCollector { tcx, items: LanguageItems::new() } LanguageItemCollector { tcx, items: LanguageItems::new() }
} }
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId, attrs: &[Attribute]) { fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
let attrs = self.tcx.hir().attrs(hir_id);
let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym); let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
if let Some((value, span)) = extract(check_name, &attrs) { if let Some((value, span)) = extract(check_name, &attrs) {
match ITEM_REFS.get(&value).cloned() { match ITEM_REFS.get(&value).cloned() {

View file

@ -120,7 +120,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
NestedVisitorMap::All(self.tcx.hir()) NestedVisitorMap::All(self.tcx.hir())
} }
fn visit_attribute(&mut self, attr: &'tcx Attribute) { fn visit_attribute(&mut self, _: rustc_hir::HirId, attr: &'tcx Attribute) {
if let Some((feature, stable, span)) = self.extract(attr) { if let Some((feature, stable, span)) = self.extract(attr) {
self.collect_feature(feature, stable, span); self.collect_feature(feature, stable, span);
} }
@ -131,7 +131,7 @@ fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
let mut collector = LibFeatureCollector::new(tcx); let mut collector = LibFeatureCollector::new(tcx);
let krate = tcx.hir().krate(); let krate = tcx.hir().krate();
for attr in krate.non_exported_macro_attrs { for attr in krate.non_exported_macro_attrs {
collector.visit_attribute(attr); collector.visit_attribute(rustc_hir::CRATE_HIR_ID, attr);
} }
intravisit::walk_crate(&mut collector, krate); intravisit::walk_crate(&mut collector, krate);
collector.lib_features collector.lib_features

View file

@ -46,7 +46,7 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
let fn_header; let fn_header;
match fk { match fk {
FnKind::Closure(..) => { FnKind::Closure => {
// Closures with a naked attribute are rejected during attribute // Closures with a naked attribute are rejected during attribute
// check. Don't validate them any further. // check. Don't validate them any further.
return; return;
@ -62,7 +62,8 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
} }
} }
let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked)); let attrs = self.tcx.hir().attrs(hir_id);
let naked = attrs.iter().any(|attr| attr.has_name(sym::naked));
if naked { if naked {
let body = self.tcx.hir().body(body_id); let body = self.tcx.hir().body(body_id);
check_abi(self.tcx, hir_id, fn_header.abi, ident_span); check_abi(self.tcx, hir_id, fn_header.abi, ident_span);

View file

@ -97,7 +97,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
fn annotate<F>( fn annotate<F>(
&mut self, &mut self,
hir_id: HirId, hir_id: HirId,
attrs: &[Attribute],
item_sp: Span, item_sp: Span,
kind: AnnotationKind, kind: AnnotationKind,
inherit_deprecation: InheritDeprecation, inherit_deprecation: InheritDeprecation,
@ -107,6 +106,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
) where ) where
F: FnOnce(&mut Self), F: FnOnce(&mut Self),
{ {
let attrs = self.tcx.hir().attrs(hir_id);
debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
let mut did_error = false; let mut did_error = false;
if !self.tcx.features().staged_api { if !self.tcx.features().staged_api {
@ -385,7 +385,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
if let Some(ctor_hir_id) = sd.ctor_hir_id() { if let Some(ctor_hir_id) = sd.ctor_hir_id() {
self.annotate( self.annotate(
ctor_hir_id, ctor_hir_id,
&i.attrs,
i.span, i.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -400,7 +399,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate( self.annotate(
i.hir_id(), i.hir_id(),
&i.attrs,
i.span, i.span,
kind, kind,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -414,7 +412,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) { fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
self.annotate( self.annotate(
ti.hir_id(), ti.hir_id(),
&ti.attrs,
ti.span, ti.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -431,7 +428,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required }; if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
self.annotate( self.annotate(
ii.hir_id(), ii.hir_id(),
&ii.attrs,
ii.span, ii.span,
kind, kind,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -446,7 +442,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) { fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
self.annotate( self.annotate(
var.id, var.id,
&var.attrs,
var.span, var.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -456,7 +451,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
if let Some(ctor_hir_id) = var.data.ctor_hir_id() { if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
v.annotate( v.annotate(
ctor_hir_id, ctor_hir_id,
&var.attrs,
var.span, var.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -474,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) { fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) {
self.annotate( self.annotate(
s.hir_id, s.hir_id,
&s.attrs,
s.span, s.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -489,7 +482,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
self.annotate( self.annotate(
i.hir_id(), i.hir_id(),
&i.attrs,
i.span, i.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -504,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
self.annotate( self.annotate(
md.hir_id(), md.hir_id(),
&md.attrs,
md.span, md.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -525,7 +516,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate( self.annotate(
p.hir_id, p.hir_id,
&p.attrs,
p.span, p.span,
kind, kind,
InheritDeprecation::No, InheritDeprecation::No,
@ -696,7 +686,6 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
annotator.annotate( annotator.annotate(
hir::CRATE_HIR_ID, hir::CRATE_HIR_ID,
&krate.item.attrs,
krate.item.span, krate.item.span,
AnnotationKind::Required, AnnotationKind::Required,
InheritDeprecation::Yes, InheritDeprecation::Yes,
@ -762,8 +751,9 @@ impl Visitor<'tcx> for Checker<'tcx> {
// error if all involved types and traits are stable, because // error if all involved types and traits are stable, because
// it will have no effect. // it will have no effect.
// See: https://github.com/rust-lang/rust/issues/55436 // See: https://github.com/rust-lang/rust/issues/55436
let attrs = self.tcx.hir().attrs(item.hir_id());
if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) = if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) =
attr::find_stability(&self.tcx.sess, &item.attrs, item.span) attr::find_stability(&self.tcx.sess, attrs, item.span)
{ {
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true }; let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
c.visit_ty(self_ty); c.visit_ty(self_ty);

View file

@ -97,7 +97,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) { fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym); let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
if let Some((lang_item, _)) = lang_items::extract(check_name, &i.attrs) { let attrs = self.tcx.hir().attrs(i.hir_id());
if let Some((lang_item, _)) = lang_items::extract(check_name, attrs) {
self.register(lang_item, i.span); self.register(lang_item, i.span);
} }
intravisit::walk_foreign_item(self, i) intravisit::walk_foreign_item(self, i)

View file

@ -16,7 +16,8 @@ struct RegistrarFinder<'tcx> {
impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> { impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> {
fn visit_item(&mut self, item: &hir::Item<'_>) { fn visit_item(&mut self, item: &hir::Item<'_>) {
if let hir::ItemKind::Fn(..) = item.kind { if let hir::ItemKind::Fn(..) = item.kind {
if self.tcx.sess.contains_name(&item.attrs, sym::plugin_registrar) { let attrs = self.tcx.hir().attrs(item.hir_id());
if self.tcx.sess.contains_name(attrs, sym::plugin_registrar) {
self.registrars.push((item.def_id, item.span)); self.registrars.push((item.def_id, item.span));
} }
} }

View file

@ -881,7 +881,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
// Non-opaque macros cannot make other items more accessible than they already are. // Non-opaque macros cannot make other items more accessible than they already are.
if attr::find_transparency(&self.tcx.sess, &md.attrs, md.ast.macro_rules).0 let attrs = self.tcx.hir().attrs(md.hir_id());
if attr::find_transparency(&self.tcx.sess, &attrs, md.ast.macro_rules).0
!= Transparency::Opaque != Transparency::Opaque
{ {
// `#[macro_export]`-ed `macro_rules!` are `Public` since they // `#[macro_export]`-ed `macro_rules!` are `Public` since they

View file

@ -1239,7 +1239,8 @@ fn compute_object_lifetime_defaults(tcx: TyCtxt<'_>) -> HirIdMap<Vec<ObjectLifet
let result = object_lifetime_defaults_for_item(tcx, generics); let result = object_lifetime_defaults_for_item(tcx, generics);
// Debugging aid. // Debugging aid.
if tcx.sess.contains_name(&item.attrs, sym::rustc_object_lifetime_default) { let attrs = tcx.hir().attrs(item.hir_id());
if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
let object_lifetime_default_reprs: String = result let object_lifetime_default_reprs: String = result
.iter() .iter()
.map(|set| match *set { .map(|set| match *set {

View file

@ -496,6 +496,7 @@ impl<'tcx> DumpVisitor<'tcx> {
if !self.span.filter_generated(item.ident.span) { if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span); let span = self.span_from_span(item.ident.span);
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def( self.dumper.dump_def(
&access_from!(self.save_ctxt, item, item.hir_id()), &access_from!(self.save_ctxt, item, item.hir_id()),
Def { Def {
@ -508,9 +509,9 @@ impl<'tcx> DumpVisitor<'tcx> {
parent: None, parent: None,
children: fields, children: fields,
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&item.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::item_signature(item, &self.save_ctxt), sig: sig::item_signature(item, &self.save_ctxt),
attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt), attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
}, },
); );
} }
@ -554,6 +555,7 @@ impl<'tcx> DumpVisitor<'tcx> {
let span = self.span_from_span(name_span); let span = self.span_from_span(name_span);
let id = id_from_hir_id(variant.id, &self.save_ctxt); let id = id_from_hir_id(variant.id, &self.save_ctxt);
let parent = Some(id_from_def_id(item.def_id.to_def_id())); let parent = Some(id_from_def_id(item.def_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.id);
self.dumper.dump_def( self.dumper.dump_def(
&access, &access,
@ -567,12 +569,9 @@ impl<'tcx> DumpVisitor<'tcx> {
parent, parent,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&variant.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::variant_signature(variant, &self.save_ctxt), sig: sig::variant_signature(variant, &self.save_ctxt),
attributes: lower_attributes( attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
variant.attrs.to_vec(),
&self.save_ctxt,
),
}, },
); );
} }
@ -594,6 +593,7 @@ impl<'tcx> DumpVisitor<'tcx> {
let span = self.span_from_span(name_span); let span = self.span_from_span(name_span);
let id = id_from_hir_id(variant.id, &self.save_ctxt); let id = id_from_hir_id(variant.id, &self.save_ctxt);
let parent = Some(id_from_def_id(item.def_id.to_def_id())); let parent = Some(id_from_def_id(item.def_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.id);
self.dumper.dump_def( self.dumper.dump_def(
&access, &access,
@ -607,12 +607,9 @@ impl<'tcx> DumpVisitor<'tcx> {
parent, parent,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&variant.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::variant_signature(variant, &self.save_ctxt), sig: sig::variant_signature(variant, &self.save_ctxt),
attributes: lower_attributes( attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
variant.attrs.to_vec(),
&self.save_ctxt,
),
}, },
); );
} }
@ -675,6 +672,7 @@ impl<'tcx> DumpVisitor<'tcx> {
let span = self.span_from_span(item.ident.span); let span = self.span_from_span(item.ident.span);
let children = let children =
methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect(); methods.iter().map(|i| id_from_def_id(i.id.def_id.to_def_id())).collect();
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def( self.dumper.dump_def(
&access_from!(self.save_ctxt, item, item.hir_id()), &access_from!(self.save_ctxt, item, item.hir_id()),
Def { Def {
@ -687,9 +685,9 @@ impl<'tcx> DumpVisitor<'tcx> {
parent: None, parent: None,
children, children,
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&item.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::item_signature(item, &self.save_ctxt), sig: sig::item_signature(item, &self.save_ctxt),
attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt), attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
}, },
); );
} }
@ -998,6 +996,7 @@ impl<'tcx> DumpVisitor<'tcx> {
hir::TraitItemKind::Const(ref ty, body) => { hir::TraitItemKind::Const(ref ty, body) => {
let body = body.map(|b| &self.tcx.hir().body(b).value); let body = body.map(|b| &self.tcx.hir().body(b).value);
let respan = respan(vis_span, hir::VisibilityKind::Public); let respan = respan(vis_span, hir::VisibilityKind::Public);
let attrs = self.tcx.hir().attrs(trait_item.hir_id());
self.process_assoc_const( self.process_assoc_const(
trait_item.hir_id(), trait_item.hir_id(),
trait_item.ident, trait_item.ident,
@ -1005,7 +1004,7 @@ impl<'tcx> DumpVisitor<'tcx> {
body, body,
trait_id, trait_id,
&respan, &respan,
&trait_item.attrs, attrs,
); );
} }
hir::TraitItemKind::Fn(ref sig, ref trait_fn) => { hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
@ -1031,6 +1030,7 @@ impl<'tcx> DumpVisitor<'tcx> {
if !self.span.filter_generated(trait_item.ident.span) { if !self.span.filter_generated(trait_item.ident.span) {
let span = self.span_from_span(trait_item.ident.span); let span = self.span_from_span(trait_item.ident.span);
let id = id_from_def_id(trait_item.def_id.to_def_id()); let id = id_from_def_id(trait_item.def_id.to_def_id());
let attrs = self.tcx.hir().attrs(trait_item.hir_id());
self.dumper.dump_def( self.dumper.dump_def(
&Access { public: true, reachable: true }, &Access { public: true, reachable: true },
@ -1044,7 +1044,7 @@ impl<'tcx> DumpVisitor<'tcx> {
parent: Some(id_from_def_id(trait_id)), parent: Some(id_from_def_id(trait_id)),
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::assoc_type_signature( sig: sig::assoc_type_signature(
trait_item.hir_id(), trait_item.hir_id(),
trait_item.ident, trait_item.ident,
@ -1052,10 +1052,7 @@ impl<'tcx> DumpVisitor<'tcx> {
default_ty.as_ref().map(|ty| &**ty), default_ty.as_ref().map(|ty| &**ty),
&self.save_ctxt, &self.save_ctxt,
), ),
attributes: lower_attributes( attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
trait_item.attrs.to_vec(),
&self.save_ctxt,
),
}, },
); );
} }
@ -1072,6 +1069,7 @@ impl<'tcx> DumpVisitor<'tcx> {
match impl_item.kind { match impl_item.kind {
hir::ImplItemKind::Const(ref ty, body) => { hir::ImplItemKind::Const(ref ty, body) => {
let body = self.tcx.hir().body(body); let body = self.tcx.hir().body(body);
let attrs = self.tcx.hir().attrs(impl_item.hir_id());
self.process_assoc_const( self.process_assoc_const(
impl_item.hir_id(), impl_item.hir_id(),
impl_item.ident, impl_item.ident,
@ -1079,7 +1077,7 @@ impl<'tcx> DumpVisitor<'tcx> {
Some(&body.value), Some(&body.value),
impl_id, impl_id,
&impl_item.vis, &impl_item.vis,
&impl_item.attrs, attrs,
); );
} }
hir::ImplItemKind::Fn(ref sig, body) => { hir::ImplItemKind::Fn(ref sig, body) => {
@ -1118,6 +1116,7 @@ impl<'tcx> DumpVisitor<'tcx> {
.map(|i| id_from_def_id(i.def_id.to_def_id())) .map(|i| id_from_def_id(i.def_id.to_def_id()))
.collect(); .collect();
let span = self.span_from_span(krate.item.span); let span = self.span_from_span(krate.item.span);
let attrs = self.tcx.hir().attrs(id);
self.dumper.dump_def( self.dumper.dump_def(
&Access { public: true, reachable: true }, &Access { public: true, reachable: true },
@ -1131,9 +1130,9 @@ impl<'tcx> DumpVisitor<'tcx> {
children, children,
parent: None, parent: None,
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(krate.item.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: None, sig: None,
attributes: lower_attributes(krate.item.attrs.to_owned(), &self.save_ctxt), attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
}, },
); );
intravisit::walk_crate(self, krate); intravisit::walk_crate(self, krate);
@ -1263,6 +1262,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
if !self.span.filter_generated(item.ident.span) { if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span); let span = self.span_from_span(item.ident.span);
let id = id_from_def_id(item.def_id.to_def_id()); let id = id_from_def_id(item.def_id.to_def_id());
let attrs = self.tcx.hir().attrs(item.hir_id());
self.dumper.dump_def( self.dumper.dump_def(
&access_from!(self.save_ctxt, item, item.hir_id()), &access_from!(self.save_ctxt, item, item.hir_id()),
@ -1276,9 +1276,9 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&item.attrs), docs: self.save_ctxt.docs_for_attrs(attrs),
sig: sig::item_signature(item, &self.save_ctxt), sig: sig::item_signature(item, &self.save_ctxt),
attributes: lower_attributes(item.attrs.to_vec(), &self.save_ctxt), attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
}, },
); );
} }

View file

@ -139,6 +139,7 @@ impl<'tcx> SaveContext<'tcx> {
pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> { pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> {
let def_id = item.def_id.to_def_id(); let def_id = item.def_id.to_def_id();
let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let qualname = format!("::{}", self.tcx.def_path_str(def_id));
let attrs = self.tcx.hir().attrs(item.hir_id());
match item.kind { match item.kind {
hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => { hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
filter!(self.span_utils, item.ident.span); filter!(self.span_utils, item.ident.span);
@ -169,9 +170,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::foreign_item_signature(item, self), sig: sig::foreign_item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ForeignItemKind::Static(ref ty, _) => { hir::ForeignItemKind::Static(ref ty, _) => {
@ -190,9 +191,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::foreign_item_signature(item, self), sig: sig::foreign_item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
// FIXME(plietar): needs a new DefKind in rls-data // FIXME(plietar): needs a new DefKind in rls-data
@ -202,6 +203,7 @@ impl<'tcx> SaveContext<'tcx> {
pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> { pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
let def_id = item.def_id.to_def_id(); let def_id = item.def_id.to_def_id();
let attrs = self.tcx.hir().attrs(item.hir_id());
match item.kind { match item.kind {
hir::ItemKind::Fn(ref sig, ref generics, _) => { hir::ItemKind::Fn(ref sig, ref generics, _) => {
let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let qualname = format!("::{}", self.tcx.def_path_str(def_id));
@ -224,9 +226,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self), sig: sig::item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ItemKind::Static(ref typ, ..) => { hir::ItemKind::Static(ref typ, ..) => {
@ -247,9 +249,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self), sig: sig::item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ItemKind::Const(ref typ, _) => { hir::ItemKind::Const(ref typ, _) => {
@ -269,9 +271,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self), sig: sig::item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ItemKind::Mod(ref m) => { hir::ItemKind::Mod(ref m) => {
@ -296,9 +298,9 @@ impl<'tcx> SaveContext<'tcx> {
.map(|i| id_from_def_id(i.def_id.to_def_id())) .map(|i| id_from_def_id(i.def_id.to_def_id()))
.collect(), .collect(),
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self), sig: sig::item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ItemKind::Enum(ref def, ref generics) => { hir::ItemKind::Enum(ref def, ref generics) => {
@ -317,9 +319,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: None, parent: None,
children: def.variants.iter().map(|v| id_from_hir_id(v.id, self)).collect(), children: def.variants.iter().map(|v| id_from_hir_id(v.id, self)).collect(),
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&item.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::item_signature(item, self), sig: sig::item_signature(item, self),
attributes: lower_attributes(item.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
})) }))
} }
hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. }) => { hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. }) => {
@ -387,6 +389,7 @@ impl<'tcx> SaveContext<'tcx> {
let id = id_from_def_id(field_def_id); let id = id_from_def_id(field_def_id);
let span = self.span_from_span(field.ident.span); let span = self.span_from_span(field.ident.span);
let attrs = self.tcx.hir().attrs(field.hir_id);
Some(Def { Some(Def {
kind: DefKind::Field, kind: DefKind::Field,
@ -398,9 +401,9 @@ impl<'tcx> SaveContext<'tcx> {
parent: Some(id_from_def_id(scope_def_id)), parent: Some(id_from_def_id(scope_def_id)),
children: vec![], children: vec![],
decl_id: None, decl_id: None,
docs: self.docs_for_attrs(&field.attrs), docs: self.docs_for_attrs(attrs),
sig: sig::field_signature(field, self), sig: sig::field_signature(field, self),
attributes: lower_attributes(field.attrs.to_vec(), self), attributes: lower_attributes(attrs.to_vec(), self),
}) })
} }
@ -424,9 +427,9 @@ impl<'tcx> SaveContext<'tcx> {
let trait_id = self.tcx.trait_id_of_impl(impl_id); let trait_id = self.tcx.trait_id_of_impl(impl_id);
let mut docs = String::new(); let mut docs = String::new();
let mut attrs = vec![]; let mut attrs = vec![];
if let Some(Node::ImplItem(item)) = hir.find(hir_id) { if let Some(Node::ImplItem(_)) = hir.find(hir_id) {
docs = self.docs_for_attrs(&item.attrs); attrs = self.tcx.hir().attrs(hir_id).to_vec();
attrs = item.attrs.to_vec(); docs = self.docs_for_attrs(&attrs);
} }
let mut decl_id = None; let mut decl_id = None;
@ -470,9 +473,9 @@ impl<'tcx> SaveContext<'tcx> {
let mut docs = String::new(); let mut docs = String::new();
let mut attrs = vec![]; let mut attrs = vec![];
if let Some(Node::TraitItem(item)) = self.tcx.hir().find(hir_id) { if let Some(Node::TraitItem(_)) = self.tcx.hir().find(hir_id) {
docs = self.docs_for_attrs(&item.attrs); attrs = self.tcx.hir().attrs(hir_id).to_vec();
attrs = item.attrs.to_vec(); docs = self.docs_for_attrs(&attrs);
} }
( (

View file

@ -1466,11 +1466,12 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
if self.span.map_or(true, |span| item.span < span) { if self.span.map_or(true, |span| item.span < span) {
if !item.span.from_expansion() { if !item.span.from_expansion() {
// Don't insert between attributes and an item. // Don't insert between attributes and an item.
if item.attrs.is_empty() { let attrs = self.tcx.hir().attrs(item.hir_id());
if attrs.is_empty() {
self.span = Some(item.span.shrink_to_lo()); self.span = Some(item.span.shrink_to_lo());
} else { } else {
// Find the first attribute on the item. // Find the first attribute on the item.
for attr in item.attrs { for attr in attrs {
if self.span.map_or(true, |span| attr.span < span) { if self.span.map_or(true, |span| attr.span < span) {
self.span = Some(attr.span.shrink_to_lo()); self.span = Some(attr.span.shrink_to_lo());
} }

View file

@ -354,7 +354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
assert!( assert!(
matches!(fk, intravisit::FnKind::Closure(..)), matches!(fk, intravisit::FnKind::Closure),
"visit_fn invoked for something other than a closure" "visit_fn invoked for something other than a closure"
); );

View file

@ -201,7 +201,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
error = true; error = true;
} }
for attr in it.attrs { let attrs = tcx.hir().attrs(main_id);
for attr in attrs {
if tcx.sess.check_name(attr, sym::track_caller) { if tcx.sess.check_name(attr, sym::track_caller) {
tcx.sess tcx.sess
.struct_span_err( .struct_span_err(
@ -300,7 +301,8 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
error = true; error = true;
} }
for attr in it.attrs { let attrs = tcx.hir().attrs(start_id);
for attr in attrs {
if tcx.sess.check_name(attr, sym::track_caller) { if tcx.sess.check_name(attr, sym::track_caller) {
tcx.sess tcx.sess
.struct_span_err( .struct_span_err(

View file

@ -863,7 +863,8 @@ fn clean_fn_or_proc_macro(
name: &mut Symbol, name: &mut Symbol,
cx: &mut DocContext<'_>, cx: &mut DocContext<'_>,
) -> ItemKind { ) -> ItemKind {
let macro_kind = item.attrs.iter().find_map(|a| { let attrs = cx.tcx.hir().attrs(item.hir_id());
let macro_kind = attrs.iter().find_map(|a| {
if a.has_name(sym::proc_macro) { if a.has_name(sym::proc_macro) {
Some(MacroKind::Bang) Some(MacroKind::Bang)
} else if a.has_name(sym::proc_macro_derive) { } else if a.has_name(sym::proc_macro_derive) {
@ -877,8 +878,7 @@ fn clean_fn_or_proc_macro(
match macro_kind { match macro_kind {
Some(kind) => { Some(kind) => {
if kind == MacroKind::Derive { if kind == MacroKind::Derive {
*name = item *name = attrs
.attrs
.lists(sym::proc_macro_derive) .lists(sym::proc_macro_derive)
.find_map(|mi| mi.ident()) .find_map(|mi| mi.ident())
.expect("proc-macro derives require a name") .expect("proc-macro derives require a name")
@ -886,7 +886,7 @@ fn clean_fn_or_proc_macro(
} }
let mut helpers = Vec::new(); let mut helpers = Vec::new();
for mi in item.attrs.lists(sym::proc_macro_derive) { for mi in attrs.lists(sym::proc_macro_derive) {
if !mi.has_name(sym::attributes) { if !mi.has_name(sym::attributes) {
continue; continue;
} }
@ -2102,8 +2102,9 @@ fn clean_extern_crate(
let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE); let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
// this is the ID of the crate itself // this is the ID of the crate itself
let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
let attrs = cx.tcx.hir().attrs(krate.hir_id());
let please_inline = krate.vis.node.is_pub() let please_inline = krate.vis.node.is_pub()
&& krate.attrs.iter().any(|a| { && attrs.iter().any(|a| {
a.has_name(sym::doc) a.has_name(sym::doc)
&& match a.meta_item_list() { && match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, sym::inline), Some(l) => attr::list_contains_name(&l, sym::inline),
@ -2121,7 +2122,7 @@ fn clean_extern_crate(
cx.tcx.parent_module(krate.hir_id()).to_def_id(), cx.tcx.parent_module(krate.hir_id()).to_def_id(),
res, res,
name, name,
Some(krate.attrs), Some(attrs),
&mut visited, &mut visited,
) { ) {
return items; return items;
@ -2130,7 +2131,7 @@ fn clean_extern_crate(
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
vec![Item { vec![Item {
name: Some(name), name: Some(name),
attrs: box krate.attrs.clean(cx), attrs: box attrs.clean(cx),
source: krate.span.clean(cx), source: krate.span.clean(cx),
def_id: crate_def_id, def_id: crate_def_id,
visibility: krate.vis.clean(cx), visibility: krate.vis.clean(cx),
@ -2152,7 +2153,8 @@ fn clean_use_statement(
return Vec::new(); return Vec::new();
} }
let inline_attr = import.attrs.lists(sym::doc).get_word_attr(sym::inline); let attrs = cx.tcx.hir().attrs(import.hir_id());
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore; let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore;
if pub_underscore { if pub_underscore {
@ -2174,7 +2176,7 @@ fn clean_use_statement(
// Don't inline doc(hidden) imports so they can be stripped at a later stage. // Don't inline doc(hidden) imports so they can be stripped at a later stage.
let mut denied = !import.vis.node.is_pub() let mut denied = !import.vis.node.is_pub()
|| pub_underscore || pub_underscore
|| import.attrs.iter().any(|a| { || attrs.iter().any(|a| {
a.has_name(sym::doc) a.has_name(sym::doc)
&& match a.meta_item_list() { && match a.meta_item_list() {
Some(l) => { Some(l) => {
@ -2214,7 +2216,7 @@ fn clean_use_statement(
cx.tcx.parent_module(import.hir_id()).to_def_id(), cx.tcx.parent_module(import.hir_id()).to_def_id(),
path.res, path.res,
name, name,
Some(import.attrs), Some(attrs),
&mut visited, &mut visited,
) { ) {
items.push(Item::from_def_id_and_parts( items.push(Item::from_def_id_and_parts(

View file

@ -106,13 +106,20 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
let tests = interface::run_compiler(config, |compiler| { let tests = interface::run_compiler(config, |compiler| {
compiler.enter(|queries| { compiler.enter(|queries| {
let lower_to_hir = queries.lower_to_hir()?; let _lower_to_hir = queries.lower_to_hir()?;
let mut opts = scrape_test_config(lower_to_hir.peek().0); let crate_name = queries.crate_name()?.peek().to_string();
let mut global_ctxt = queries.global_ctxt()?.take();
let collector = global_ctxt.enter(|tcx| {
let krate = tcx.hir().krate();
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let mut opts = scrape_test_config(crate_attrs);
opts.display_warnings |= options.display_warnings; opts.display_warnings |= options.display_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores; let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new( let mut collector = Collector::new(
queries.crate_name()?.peek().to_string(), crate_name,
options, options,
false, false,
opts, opts,
@ -121,11 +128,6 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
enable_per_target_ignores, enable_per_target_ignores,
); );
let mut global_ctxt = queries.global_ctxt()?.take();
global_ctxt.enter(|tcx| {
let krate = tcx.hir().krate();
let mut hir_collector = HirCollector { let mut hir_collector = HirCollector {
sess: compiler.session(), sess: compiler.session(),
collector: &mut collector, collector: &mut collector,
@ -137,13 +139,14 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
}; };
hir_collector.visit_testable( hir_collector.visit_testable(
"".to_string(), "".to_string(),
&krate.item.attrs,
CRATE_HIR_ID, CRATE_HIR_ID,
krate.item.span, krate.item.span,
|this| { |this| {
intravisit::walk_crate(this, krate); intravisit::walk_crate(this, krate);
}, },
); );
collector
}); });
compiler.session().abort_if_errors(); compiler.session().abort_if_errors();
@ -168,15 +171,13 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
} }
// Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade. // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
fn scrape_test_config(krate: &::rustc_hir::Crate<'_>) -> TestOptions { fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
let mut opts = let mut opts =
TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() }; TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
let test_attrs: Vec<_> = krate let test_attrs: Vec<_> = attrs
.item
.attrs
.iter() .iter()
.filter(|a| a.has_name(sym::doc)) .filter(|a| a.has_name(sym::doc))
.flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new)) .flat_map(|a| a.meta_item_list().unwrap_or_else(Vec::new))
@ -991,11 +992,11 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
fn visit_testable<F: FnOnce(&mut Self)>( fn visit_testable<F: FnOnce(&mut Self)>(
&mut self, &mut self,
name: String, name: String,
attrs: &[ast::Attribute],
hir_id: HirId, hir_id: HirId,
sp: Span, sp: Span,
nested: F, nested: F,
) { ) {
let attrs = self.tcx.hir().attrs(hir_id);
let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None); let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs, None);
if let Some(ref cfg) = attrs.cfg { if let Some(ref cfg) = attrs.cfg {
if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) { if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) {
@ -1053,45 +1054,27 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
item.ident.to_string() item.ident.to_string()
}; };
self.visit_testable(name, &item.attrs, item.hir_id(), item.span, |this| { self.visit_testable(name, item.hir_id(), item.span, |this| {
intravisit::walk_item(this, item); intravisit::walk_item(this, item);
}); });
} }
fn visit_trait_item(&mut self, item: &'hir hir::TraitItem<'_>) { fn visit_trait_item(&mut self, item: &'hir hir::TraitItem<'_>) {
self.visit_testable( self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
item.ident.to_string(),
&item.attrs,
item.hir_id(),
item.span,
|this| {
intravisit::walk_trait_item(this, item); intravisit::walk_trait_item(this, item);
}, });
);
} }
fn visit_impl_item(&mut self, item: &'hir hir::ImplItem<'_>) { fn visit_impl_item(&mut self, item: &'hir hir::ImplItem<'_>) {
self.visit_testable( self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
item.ident.to_string(),
&item.attrs,
item.hir_id(),
item.span,
|this| {
intravisit::walk_impl_item(this, item); intravisit::walk_impl_item(this, item);
}, });
);
} }
fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem<'_>) { fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem<'_>) {
self.visit_testable( self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
item.ident.to_string(),
&item.attrs,
item.hir_id(),
item.span,
|this| {
intravisit::walk_foreign_item(this, item); intravisit::walk_foreign_item(this, item);
}, });
);
} }
fn visit_variant( fn visit_variant(
@ -1100,13 +1083,13 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
g: &'hir hir::Generics<'_>, g: &'hir hir::Generics<'_>,
item_id: hir::HirId, item_id: hir::HirId,
) { ) {
self.visit_testable(v.ident.to_string(), &v.attrs, v.id, v.span, |this| { self.visit_testable(v.ident.to_string(), v.id, v.span, |this| {
intravisit::walk_variant(this, v, g, item_id); intravisit::walk_variant(this, v, g, item_id);
}); });
} }
fn visit_struct_field(&mut self, f: &'hir hir::StructField<'_>) { fn visit_struct_field(&mut self, f: &'hir hir::StructField<'_>) {
self.visit_testable(f.ident.to_string(), &f.attrs, f.hir_id, f.span, |this| { self.visit_testable(f.ident.to_string(), f.hir_id, f.span, |this| {
intravisit::walk_struct_field(this, f); intravisit::walk_struct_field(this, f);
}); });
} }
@ -1114,7 +1097,6 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) { fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) {
self.visit_testable( self.visit_testable(
macro_def.ident.to_string(), macro_def.ident.to_string(),
&macro_def.attrs,
macro_def.hir_id(), macro_def.hir_id(),
macro_def.span, macro_def.span,
|_| (), |_| (),

View file

@ -285,10 +285,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
return; return;
} }
let attrs = self.cx.tcx.hir().attrs(item.hir_id());
// If there was a private module in the current path then don't bother inlining // If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway. // anything as it will probably be stripped anyway.
if item.vis.node.is_pub() && self.inside_public_path { if item.vis.node.is_pub() && self.inside_public_path {
let please_inline = item.attrs.iter().any(|item| match item.meta_item_list() { let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
Some(ref list) if item.has_name(sym::doc) => { Some(ref list) if item.has_name(sym::doc) => {
list.iter().any(|i| i.has_name(sym::inline)) list.iter().any(|i| i.has_name(sym::inline))
} }

View file

@ -335,7 +335,7 @@ enum EnumAddMustUse {
} }
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[must_use] #[must_use]
enum EnumAddMustUse { enum EnumAddMustUse {
@ -353,7 +353,7 @@ enum EnumAddReprC {
} }
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail2", except="type_of")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[repr(C)] #[repr(C)]
enum EnumAddReprC { enum EnumAddReprC {

View file

@ -154,7 +154,7 @@ extern "C" {
} }
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[link_args = "-foo -bar -baz"] #[link_args = "-foo -bar -baz"]
extern "C" { extern "C" {
@ -169,7 +169,7 @@ extern "C" {
} }
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")] #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[link(name = "bar")] #[link(name = "bar")]
extern "C" { extern "C" {

View file

@ -194,7 +194,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
pub fn inline() {} pub fn inline() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[inline] #[inline]
pub fn inline() {} pub fn inline() {}
@ -206,7 +206,7 @@ pub fn inline() {}
pub fn inline_never() {} pub fn inline_never() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[inline(never)] #[inline(never)]
pub fn inline_never() {} pub fn inline_never() {}
@ -217,7 +217,7 @@ pub fn inline_never() {}
pub fn no_mangle() {} pub fn no_mangle() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[no_mangle] #[no_mangle]
pub fn no_mangle() {} pub fn no_mangle() {}
@ -228,7 +228,7 @@ pub fn no_mangle() {}
pub fn linkage() {} pub fn linkage() {}
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")] #[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")] #[rustc_clean(cfg = "cfail3")]
#[linkage = "weak_odr"] #[linkage = "weak_odr"]
pub fn linkage() {} pub fn linkage() {}

View file

@ -214,7 +214,7 @@ impl Foo {
#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
impl Foo { impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[inline] #[inline]
pub fn make_method_inline(&self) -> u8 { 0 } pub fn make_method_inline(&self) -> u8 { 0 }
@ -431,7 +431,7 @@ impl Foo {
#[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
impl Foo { impl Foo {
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[no_mangle] #[no_mangle]
pub fn add_no_mangle_to_method(&self) { } pub fn add_no_mangle_to_method(&self) { }

View file

@ -41,7 +41,7 @@ static mut STATIC_MUTABILITY: u8 = 0;
static STATIC_LINKAGE: u8 = 0; static STATIC_LINKAGE: u8 = 0;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[linkage="weak_odr"] #[linkage="weak_odr"]
static STATIC_LINKAGE: u8 = 0; static STATIC_LINKAGE: u8 = 0;
@ -52,7 +52,7 @@ static STATIC_LINKAGE: u8 = 0;
static STATIC_NO_MANGLE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[no_mangle] #[no_mangle]
static STATIC_NO_MANGLE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0;
@ -63,7 +63,7 @@ static STATIC_NO_MANGLE: u8 = 0;
static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")] #[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")] #[rustc_clean(cfg="cfail3")]
#[thread_local] #[thread_local]
static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0;

View file

@ -24,8 +24,8 @@
pub struct LayoutPacked; pub struct LayoutPacked;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="hir_owner_nodes", cfg="cfail2")]
#[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")]
#[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")]
#[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")]
@ -41,8 +41,8 @@ pub struct LayoutPacked;
struct LayoutC; struct LayoutC;
#[cfg(not(cfail1))] #[cfg(not(cfail1))]
#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")] #[rustc_clean(label="hir_owner_nodes", cfg="cfail2")]
#[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")]
#[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")]
#[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")]

View file

@ -457,7 +457,7 @@ impl AddNoMangleToMethod for Foo {
#[rustc_clean(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner", cfg="cfail3")]
impl AddNoMangleToMethod for Foo { impl AddNoMangleToMethod for Foo {
#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner", cfg="cfail3")]
#[no_mangle] #[no_mangle]
fn add_no_mangle_to_method(&self) { } fn add_no_mangle_to_method(&self) { }
@ -478,7 +478,7 @@ impl MakeMethodInline for Foo {
#[rustc_clean(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner", cfg="cfail3")]
impl MakeMethodInline for Foo { impl MakeMethodInline for Foo {
#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner", cfg="cfail2")]
#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner", cfg="cfail3")]
#[inline] #[inline]
fn make_method_inline(&self) -> u8 { 0 } fn make_method_inline(&self) -> u8 { 0 }

View file

@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass {
}; };
let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
if !item.attrs.iter().any(allowed) { if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) {
cx.lint(MISSING_ALLOWED_ATTR, |lint| { cx.lint(MISSING_ALLOWED_ATTR, |lint| {
lint.build("Missing 'allowed_attr' attribute").set_span(span).emit() lint.build("Missing 'allowed_attr' attribute").set_span(span).emit()
}); });

View file

@ -28,8 +28,9 @@ macro_rules! fake_lint_pass {
impl LateLintPass<'_> for $struct { impl LateLintPass<'_> for $struct {
fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
$( $(
if !cx.sess().contains_name(&krate.item.attrs, $attr) { if !cx.sess().contains_name(attrs, $attr) {
cx.lint(CRATE_NOT_OKAY, |lint| { cx.lint(CRATE_NOT_OKAY, |lint| {
let msg = format!("crate is not marked with #![{}]", $attr); let msg = format!("crate is not marked with #![{}]", $attr);
lint.build(&msg).set_span(krate.item.span).emit() lint.build(&msg).set_span(krate.item.span).emit()

View file

@ -27,7 +27,8 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
impl<'tcx> LateLintPass<'tcx> for Pass { impl<'tcx> LateLintPass<'tcx> for Pass {
fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) {
if !cx.sess().contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) { let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
cx.lint(CRATE_NOT_OKAY, |lint| { cx.lint(CRATE_NOT_OKAY, |lint| {
lint.build("crate is not marked with #![crate_okay]") lint.build("crate is not marked with #![crate_okay]")
.set_span(krate.item.span) .set_span(krate.item.span)

View file

@ -493,6 +493,30 @@ LL | #![feature(rust1)]
| |
= note: `#[warn(stable_features)]` on by default = note: `#[warn(stable_features)]` on by default
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:1
|
LL | #![plugin_registrar]
| ^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
|
LL | #![should_panic]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
|
LL | #![ignore]
| ^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
|
LL | #![proc_macro_derive()]
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
| |
@ -517,6 +541,12 @@ warning: unused attribute
LL | #[macro_use] impl S { } LL | #[macro_use] impl S { }
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:1
|
LL | #[macro_export]
| ^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:17
| |
@ -548,10 +578,10 @@ LL | #[macro_export] impl S { }
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:223:1
| |
LL | #[macro_export] LL | #[plugin_registrar]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
@ -577,12 +607,6 @@ warning: unused attribute
LL | #[plugin_registrar] impl S { } LL | #[plugin_registrar] impl S { }
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:223:1
|
LL | #[plugin_registrar]
| ^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5
| |
@ -607,6 +631,12 @@ warning: unused attribute
LL | #[path = "3800"] impl S { } LL | #[path = "3800"] impl S { }
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:1
|
LL | #[automatically_derived]
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:17
| |
@ -638,10 +668,10 @@ LL | #[automatically_derived] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:1
| |
LL | #[automatically_derived] LL | #[should_panic]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:17
@ -674,10 +704,10 @@ LL | #[should_panic] impl S { }
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:1
| |
LL | #[should_panic] LL | #[ignore]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:17
@ -710,10 +740,10 @@ LL | #[ignore] impl S { }
| ^^^^^^^^^ | ^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:1
| |
LL | #[ignore] LL | #[no_implicit_prelude]
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:402:17
@ -746,10 +776,10 @@ LL | #[no_implicit_prelude] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1
| |
LL | #[no_implicit_prelude] LL | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:17
@ -781,12 +811,6 @@ warning: unused attribute
LL | #[reexport_test_harness_main = "2900"] impl S { } LL | #[reexport_test_harness_main = "2900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:1
|
LL | #[reexport_test_harness_main = "2900"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
| |
@ -811,6 +835,18 @@ warning: unused attribute
LL | #[macro_escape] impl S { } LL | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1
|
LL | #[no_std]
| ^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1
|
LL | #[no_std]
| ^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17
| |
@ -872,16 +908,16 @@ LL | #[no_std] impl S { }
| ^^^^^^^^^ | ^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
| |
LL | #[no_std] LL | #[crate_name = "0900"]
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
| |
LL | #[no_std] LL | #[crate_name = "0900"]
| ^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:17
@ -944,15 +980,15 @@ LL | #[crate_name = "0900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1
| |
LL | #[crate_name = "0900"] LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1
| |
LL | #[crate_name = "0900"] LL | #[crate_type = "0800"]
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
@ -1016,16 +1052,16 @@ LL | #[crate_type = "0800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1
| |
LL | #[crate_type = "0800"] LL | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1
| |
LL | #[crate_type = "0800"] LL | #[feature(x0600)]
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:17
@ -1088,16 +1124,16 @@ LL | #[feature(x0600)] impl S { }
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1
| |
LL | #[feature(x0600)] LL | #[no_main]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1
| |
LL | #[feature(x0600)] LL | #[no_main]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:17
@ -1160,16 +1196,16 @@ LL | #[no_main] impl S { }
| ^^^^^^^^^^ | ^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1
| |
LL | #[no_main] LL | #[recursion_limit="0200"]
| ^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1
| |
LL | #[no_main] LL | #[recursion_limit="0200"]
| ^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:17
@ -1232,16 +1268,16 @@ LL | #[recursion_limit="0200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1
| |
LL | #[recursion_limit="0200"] LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:1 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1
| |
LL | #[recursion_limit="0200"] LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:17 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:17
@ -1303,41 +1339,5 @@ warning: crate-level attribute should be an inner attribute: add an exclamation
LL | #[type_length_limit="0100"] impl S { } LL | #[type_length_limit="0100"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1
|
LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:1
|
LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:1
|
LL | #![plugin_registrar]
| ^^^^^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
|
LL | #![should_panic]
| ^^^^^^^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
|
LL | #![ignore]
| ^^^^^^^^^^
warning: unused attribute
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
|
LL | #![proc_macro_derive()]
| ^^^^^^^^^^^^^^^^^^^^^^^
warning: 205 warnings emitted warning: 205 warnings emitted

View file

@ -1,8 +1,8 @@
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:6:1 --> $DIR/unused-attr.rs:4:1
| |
LL | #[rustc_dummy] LL | #![rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/unused-attr.rs:1:9 --> $DIR/unused-attr.rs:1:9
@ -11,13 +11,13 @@ LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:9:1 --> $DIR/unused-attr.rs:6:1
| |
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:14:5 --> $DIR/unused-attr.rs:9:1
| |
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -29,13 +29,7 @@ LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:22:9 --> $DIR/unused-attr.rs:14:5
|
LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:20:5
| |
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -47,7 +41,13 @@ LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:30:9 --> $DIR/unused-attr.rs:20:5
|
LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:22:9
| |
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -59,7 +59,7 @@ LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:37:5 --> $DIR/unused-attr.rs:30:9
| |
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -70,6 +70,18 @@ error: unused attribute
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:37:5
|
LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:41:1
|
LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^
error: unused attribute error: unused attribute
--> $DIR/unused-attr.rs:43:5 --> $DIR/unused-attr.rs:43:5
| |
@ -82,17 +94,5 @@ error: unused attribute
LL | #[rustc_dummy] LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:41:1
|
LL | #[rustc_dummy]
| ^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr.rs:4:1
|
LL | #![rustc_dummy]
| ^^^^^^^^^^^^^^^
error: aborting due to 15 previous errors error: aborting due to 15 previous errors

View file

@ -276,14 +276,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
} }
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
if is_relevant_item(cx, item) { if is_relevant_item(cx, item) {
check_attrs(cx, item.span, item.ident.name, &item.attrs) check_attrs(cx, item.span, item.ident.name, attrs)
} }
match item.kind { match item.kind {
ItemKind::ExternCrate(..) | ItemKind::Use(..) => { ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
let skip_unused_imports = item.attrs.iter().any(|attr| attr.has_name(sym::macro_use)); let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
for attr in item.attrs { for attr in attrs {
if in_external_macro(cx.sess(), attr.span) { if in_external_macro(cx.sess(), attr.span) {
return; return;
} }
@ -353,13 +354,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
if is_relevant_impl(cx, item) { if is_relevant_impl(cx, item) {
check_attrs(cx, item.span, item.ident.name, &item.attrs) check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
} }
} }
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
if is_relevant_trait(cx, item) { if is_relevant_trait(cx, item) {
check_attrs(cx, item.span, item.ident.name, &item.attrs) check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
} }
} }
} }

View file

@ -76,8 +76,8 @@ impl CognitiveComplexity {
if rust_cc > self.limit.limit() { if rust_cc > self.limit.limit() {
let fn_span = match kind { let fn_span = match kind {
FnKind::ItemFn(ident, _, _, _, _) | FnKind::Method(ident, _, _, _) => ident.span, FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
FnKind::Closure(_) => { FnKind::Closure => {
let header_span = body_span.with_hi(decl.output.span().lo()); let header_span = body_span.with_hi(decl.output.span().lo());
let pos = snippet_opt(cx, header_span).and_then(|snip| { let pos = snippet_opt(cx, header_span).and_then(|snip| {
let low_offset = snip.find('|')?; let low_offset = snip.find('|')?;

View file

@ -170,7 +170,8 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
}) = item.kind }) = item.kind
{ {
let ty = cx.tcx.type_of(item.def_id); let ty = cx.tcx.type_of(item.def_id);
let is_automatically_derived = is_automatically_derived(&*item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let is_automatically_derived = is_automatically_derived(attrs);
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);

View file

@ -208,12 +208,14 @@ impl_lint_pass!(DocMarkdown =>
); );
impl<'tcx> LateLintPass<'tcx> for DocMarkdown { impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { fn check_crate(&mut self, cx: &LateContext<'tcx>, _: &'tcx hir::Crate<'_>) {
check_attrs(cx, &self.valid_idents, &krate.item.attrs); let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
check_attrs(cx, &self.valid_idents, attrs);
} }
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let headers = check_attrs(cx, &self.valid_idents, &item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let headers = check_attrs(cx, &self.valid_idents, attrs);
match item.kind { match item.kind {
hir::ItemKind::Fn(ref sig, _, body_id) => { hir::ItemKind::Fn(ref sig, _, body_id) => {
if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
@ -249,7 +251,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
} }
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
let headers = check_attrs(cx, &self.valid_idents, &item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let headers = check_attrs(cx, &self.valid_idents, attrs);
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) { if !in_external_macro(cx.tcx.sess, item.span) {
lint_for_missing_headers(cx, item.hir_id(), item.span, sig, headers, None, None); lint_for_missing_headers(cx, item.hir_id(), item.span, sig, headers, None, None);
@ -258,7 +261,8 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
} }
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
let headers = check_attrs(cx, &self.valid_idents, &item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let headers = check_attrs(cx, &self.valid_idents, attrs);
if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) { if self.in_trait_impl || in_external_macro(cx.tcx.sess, item.span) {
return; return;
} }

View file

@ -73,7 +73,8 @@ impl LateLintPass<'_> for ExhaustiveItems {
if_chain! { if_chain! {
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind; if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
if cx.access_levels.is_exported(item.hir_id()); if cx.access_levels.is_exported(item.hir_id());
if !item.attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); let attrs = cx.tcx.hir().attrs(item.hir_id());
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then { then {
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind { let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
if v.fields().iter().any(|f| !f.vis.node.is_pub()) { if v.fields().iter().any(|f| !f.vis.node.is_pub()) {

View file

@ -251,9 +251,9 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
let unsafety = match kind { let unsafety = match kind {
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety, intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _) => unsafety,
intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety, intravisit::FnKind::Method(_, sig, _) => sig.header.unsafety,
intravisit::FnKind::Closure(_) => return, intravisit::FnKind::Closure => return,
}; };
// don't warn for implementations, it's not their fault // don't warn for implementations, it's not their fault
@ -267,9 +267,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
.. ..
}, },
_, _,
_,
) )
| intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => { | intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _) => {
self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi())) self.check_arg_number(cx, decl, span.with_hi(decl.output.span().hi()))
}, },
_ => {}, _ => {},
@ -281,7 +280,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
} }
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attr = must_use_attr(&item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = must_use_attr(attrs);
if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind { if let hir::ItemKind::Fn(ref sig, ref _generics, ref body_id) = item.kind {
let is_public = cx.access_levels.is_exported(item.hir_id()); let is_public = cx.access_levels.is_exported(item.hir_id());
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
@ -292,7 +292,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
return; return;
} }
if is_public && !is_proc_macro(cx.sess(), &item.attrs) && attr_by_name(&item.attrs, "no_mangle").is_none() { if is_public && !is_proc_macro(cx.sess(), attrs) && attr_by_name(attrs, "no_mangle").is_none() {
check_must_use_candidate( check_must_use_candidate(
cx, cx,
&sig.decl, &sig.decl,
@ -313,11 +313,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() { if is_public && trait_ref_of_method(cx, item.hir_id()).is_none() {
check_result_unit_err(cx, &sig.decl, item.span, fn_header_span); check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
} }
let attr = must_use_attr(&item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = must_use_attr(attrs);
if let Some(attr) = attr { if let Some(attr) = attr {
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
} else if is_public } else if is_public
&& !is_proc_macro(cx.sess(), &item.attrs) && !is_proc_macro(cx.sess(), attrs)
&& trait_ref_of_method(cx, item.hir_id()).is_none() && trait_ref_of_method(cx, item.hir_id()).is_none()
{ {
check_must_use_candidate( check_must_use_candidate(
@ -345,7 +346,8 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
check_result_unit_err(cx, &sig.decl, item.span, fn_header_span); check_result_unit_err(cx, &sig.decl, item.span, fn_header_span);
} }
let attr = must_use_attr(&item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = must_use_attr(attrs);
if let Some(attr) = attr { if let Some(attr) = attr {
check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr); check_needless_must_use(cx, &sig.decl, item.hir_id(), item.span, fn_header_span, attr);
} }
@ -353,7 +355,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
let body = cx.tcx.hir().body(eid); let body = cx.tcx.hir().body(eid);
Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id()); Self::check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.hir_id());
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), &item.attrs) { if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
check_must_use_candidate( check_must_use_candidate(
cx, cx,
&sig.decl, &sig.decl,

View file

@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
_: Span, _: Span,
hir_id: HirId, hir_id: HirId,
) { ) {
if let FnKind::Closure(_) = kind { if let FnKind::Closure = kind {
return; return;
} }
let ret_ty = utils::return_ty(cx, hir_id); let ret_ty = utils::return_ty(cx, hir_id);

View file

@ -34,7 +34,8 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]);
impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind { if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind {
check_attrs(cx, item.ident.name, &item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
check_attrs(cx, item.ident.name, attrs);
} }
} }
} }

View file

@ -578,7 +578,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
// also check for empty `loop {}` statements, skipping those in #[panic_handler] // also check for empty `loop {}` statements, skipping those in #[panic_handler]
if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) { if block.stmts.is_empty() && block.expr.is_none() && !is_in_panic_handler(cx, expr) {
let msg = "empty `loop {}` wastes CPU cycles"; let msg = "empty `loop {}` wastes CPU cycles";
let help = if is_no_std_crate(cx.tcx.hir().krate()) { let help = if is_no_std_crate(cx) {
"you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body" "you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body"
} else { } else {
"you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body" "you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body"

View file

@ -107,8 +107,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
if_chain! { if_chain! {
if cx.sess().opts.edition >= Edition::Edition2018; if cx.sess().opts.edition >= Edition::Edition2018;
if let hir::ItemKind::Use(path, _kind) = &item.kind; if let hir::ItemKind::Use(path, _kind) = &item.kind;
if let Some(mac_attr) = item let attrs = cx.tcx.hir().attrs(item.hir_id());
.attrs if let Some(mac_attr) = attrs
.iter() .iter()
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string())); .find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
if let Res::Def(DefKind::Mod, id) = path.res; if let Res::Def(DefKind::Mod, id) = path.res;

View file

@ -32,8 +32,8 @@ pub struct MainRecursion {
impl_lint_pass!(MainRecursion => [MAIN_RECURSION]); impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
impl LateLintPass<'_> for MainRecursion { impl LateLintPass<'_> for MainRecursion {
fn check_crate(&mut self, _: &LateContext<'_>, krate: &Crate<'_>) { fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
self.has_no_std_attr = is_no_std_crate(krate); self.has_no_std_attr = is_no_std_crate(cx);
} }
fn check_expr_post(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_expr_post(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {

View file

@ -1207,11 +1207,11 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
if b0 != b1; if b0 != b1;
let if_guard = &b0_arms[0].guard; let if_guard = &b0_arms[0].guard;
if if_guard.is_none() || b0_arms.len() == 1; if if_guard.is_none() || b0_arms.len() == 1;
if b0_arms[0].attrs.is_empty(); if cx.tcx.hir().attrs(b0_arms[0].hir_id).is_empty();
if b0_arms[1..].iter() if b0_arms[1..].iter()
.all(|arm| { .all(|arm| {
find_bool_lit(&arm.body.kind, desugared).map_or(false, |b| b == b0) && find_bool_lit(&arm.body.kind, desugared).map_or(false, |b| b == b0) &&
arm.guard.is_none() && arm.attrs.is_empty() arm.guard.is_none() && cx.tcx.hir().attrs(arm.hir_id).is_empty()
}); });
then { then {
// The suggestion may be incorrect, because some arms can have `cfg` attributes // The suggestion may be incorrect, because some arms can have `cfg` attributes

View file

@ -278,7 +278,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
span: Span, span: Span,
_: HirId, _: HirId,
) { ) {
if let FnKind::Closure(_) = k { if let FnKind::Closure = k {
// Does not apply to closures // Does not apply to closures
return; return;
} }

View file

@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
return; return;
} }
}, },
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
let mir = cx.tcx.optimized_mir(def_id); let mir = cx.tcx.optimized_mir(def_id);

View file

@ -127,7 +127,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
} }
fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
self.check_missing_docs_attrs(cx, &krate.item.attrs, krate.item.span, "the", "crate"); let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
self.check_missing_docs_attrs(cx, attrs, krate.item.span, "the", "crate");
} }
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
@ -160,13 +161,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
self.check_missing_docs_attrs(cx, &it.attrs, it.span, article, desc); let attrs = cx.tcx.hir().attrs(it.hir_id());
self.check_missing_docs_attrs(cx, attrs, it.span, article, desc);
} }
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, article, desc); let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc);
} }
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
@ -181,16 +184,19 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
} }
let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id()); let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, article, desc); let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
} }
fn check_struct_field(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::StructField<'_>) { fn check_struct_field(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::StructField<'_>) {
if !sf.is_positional() { if !sf.is_positional() {
self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a", "struct field"); let attrs = cx.tcx.hir().attrs(sf.hir_id);
self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field");
} }
} }
fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) { fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
self.check_missing_docs_attrs(cx, &v.attrs, v.span, "a", "variant"); let attrs = cx.tcx.hir().attrs(v.id);
self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
} }
} }

View file

@ -93,7 +93,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
match it.kind { match it.kind {
hir::ItemKind::Fn(..) => { hir::ItemKind::Fn(..) => {
let desc = "a function"; let desc = "a function";
check_missing_inline_attrs(cx, &it.attrs, it.span, desc); let attrs = cx.tcx.hir().attrs(it.hir_id());
check_missing_inline_attrs(cx, attrs, it.span, desc);
}, },
hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => { hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => {
// note: we need to check if the trait is exported so we can't use // note: we need to check if the trait is exported so we can't use
@ -108,7 +109,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
// an impl is not provided // an impl is not provided
let desc = "a default trait method"; let desc = "a default trait method";
let item = cx.tcx.hir().trait_item(tit.id); let item = cx.tcx.hir().trait_item(tit.id);
check_missing_inline_attrs(cx, &item.attrs, item.span, desc); let attrs = cx.tcx.hir().attrs(item.hir_id());
check_missing_inline_attrs(cx, attrs, item.span, desc);
} }
}, },
} }
@ -160,6 +162,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
} }
} }
check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc); let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
} }
} }

View file

@ -115,8 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
} }
} }
fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if is_automatically_derived(item.attrs) { let attrs = cx.tcx.hir().attrs(item.hir_id());
if is_automatically_derived(attrs) {
debug_assert!(self.derived_item.is_none()); debug_assert!(self.derived_item.is_none());
self.derived_item = Some(item.def_id); self.derived_item = Some(item.def_id);
} }

View file

@ -80,13 +80,14 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
} }
match kind { match kind {
FnKind::ItemFn(.., header, _, attrs) => { FnKind::ItemFn(.., header, _) => {
let attrs = cx.tcx.hir().attrs(hir_id);
if header.abi != Abi::Rust || requires_exact_signature(attrs) { if header.abi != Abi::Rust || requires_exact_signature(attrs) {
return; return;
} }
}, },
FnKind::Method(..) => (), FnKind::Method(..) => (),
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
// Exclude non-inherent impls // Exclude non-inherent impls

View file

@ -43,9 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn {
span: Span, span: Span,
hir_id: hir::HirId, hir_id: hir::HirId,
) { ) {
if !matches!(fn_kind, FnKind::Closure(_)) if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) {
&& is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type)
{
lint_impl_body(cx, span, body); lint_impl_body(cx, span, body);
} }
} }

View file

@ -35,7 +35,8 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if_chain! { if_chain! {
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind; if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
if !is_automatically_derived(&*item.attrs); let attrs = cx.tcx.hir().attrs(item.hir_id());
if !is_automatically_derived(attrs);
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
if trait_ref.path.res.def_id() == eq_trait; if trait_ref.path.res.def_id() == eq_trait;
then { then {

View file

@ -224,10 +224,11 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
} }
match kind { match kind {
FnKind::ItemFn(.., header, _, attrs) => { FnKind::ItemFn(.., header, _) => {
if header.abi != Abi::Rust { if header.abi != Abi::Rust {
return; return;
} }
let attrs = cx.tcx.hir().attrs(hir_id);
for a in attrs { for a in attrs {
if let Some(meta_items) = a.meta_item_list() { if let Some(meta_items) = a.meta_item_list() {
if a.has_name(sym::proc_macro_derive) if a.has_name(sym::proc_macro_derive)
@ -239,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
} }
}, },
FnKind::Method(..) => (), FnKind::Method(..) => (),
FnKind::Closure(..) => return, FnKind::Closure => return,
} }
// Exclude non-inherent impls // Exclude non-inherent impls

View file

@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
if let Some(stmt) = block.stmts.iter().last(); if let Some(stmt) = block.stmts.iter().last();
if let StmtKind::Local(local) = &stmt.kind; if let StmtKind::Local(local) = &stmt.kind;
if local.ty.is_none(); if local.ty.is_none();
if local.attrs.is_empty(); if cx.tcx.hir().attrs(local.hir_id).is_empty();
if let Some(initexpr) = &local.init; if let Some(initexpr) = &local.init;
if let PatKind::Binding(.., ident, _) = local.pat.kind; if let PatKind::Binding(.., ident, _) = local.pat.kind;
if let ExprKind::Path(qpath) = &retexpr.kind; if let ExprKind::Path(qpath) = &retexpr.kind;
@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
_: HirId, _: HirId,
) { ) {
match kind { match kind {
FnKind::Closure(_) => { FnKind::Closure => {
// when returning without value in closure, replace this `return` // when returning without value in closure, replace this `return`
// with an empty block to prevent invalid suggestion (see #6501) // with an empty block to prevent invalid suggestion (see #6501)
let replacement = if let ExprKind::Ret(None) = &body.value.kind { let replacement = if let ExprKind::Ret(None) = &body.value.kind {
@ -177,7 +177,8 @@ fn check_final_expr<'tcx>(
// simple return is always "bad" // simple return is always "bad"
ExprKind::Ret(ref inner) => { ExprKind::Ret(ref inner) => {
// allow `#[cfg(a)] return a; #[cfg(b)] return b;` // allow `#[cfg(a)] return a; #[cfg(b)] return b;`
if !expr.attrs.iter().any(attr_is_cfg) { let attrs = cx.tcx.hir().attrs(expr.hir_id);
if !attrs.iter().any(attr_is_cfg) {
let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner)); let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
if !borrows { if !borrows {
emit_return_lint( emit_return_lint(

View file

@ -66,12 +66,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
) { ) {
// Abort if public function/method or closure. // Abort if public function/method or closure.
match fn_kind { match fn_kind {
FnKind::ItemFn(.., visibility, _) | FnKind::Method(.., Some(visibility), _) => { FnKind::ItemFn(.., visibility) | FnKind::Method(.., Some(visibility)) => {
if visibility.node.is_pub() { if visibility.node.is_pub() {
return; return;
} }
}, },
FnKind::Closure(..) => return, FnKind::Closure => return,
_ => (), _ => (),
} }

View file

@ -2,7 +2,7 @@
//! to generate a clippy lint detecting said code automatically. //! to generate a clippy lint detecting said code automatically.
use crate::utils::get_attr; use crate::utils::get_attr;
use rustc_ast::ast::{Attribute, LitFloatType, LitKind}; use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::walk_list; use rustc_ast::walk_list;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir; use rustc_hir as hir;
@ -10,7 +10,6 @@ use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_session::Session;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {
@ -66,7 +65,7 @@ fn done() {
impl<'tcx> LateLintPass<'tcx> for Author { impl<'tcx> LateLintPass<'tcx> for Author {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx, item.hir_id()) {
return; return;
} }
prelude(); prelude();
@ -75,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx, item.hir_id()) {
return; return;
} }
prelude(); prelude();
@ -84,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx, item.hir_id()) {
return; return;
} }
prelude(); prelude();
@ -93,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_variant(&mut self, cx: &LateContext<'tcx>, var: &'tcx hir::Variant<'_>) { fn check_variant(&mut self, cx: &LateContext<'tcx>, var: &'tcx hir::Variant<'_>) {
if !has_attr(cx.sess(), &var.attrs) { if !has_attr(cx, var.id) {
return; return;
} }
prelude(); prelude();
@ -103,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::StructField<'_>) { fn check_struct_field(&mut self, cx: &LateContext<'tcx>, field: &'tcx hir::StructField<'_>) {
if !has_attr(cx.sess(), &field.attrs) { if !has_attr(cx, field.hir_id) {
return; return;
} }
prelude(); prelude();
@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if !has_attr(cx.sess(), &expr.attrs) { if !has_attr(cx, expr.hir_id) {
return; return;
} }
prelude(); prelude();
@ -121,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) { fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) {
if !has_attr(cx.sess(), &arm.attrs) { if !has_attr(cx, arm.hir_id) {
return; return;
} }
prelude(); prelude();
@ -130,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) {
if !has_attr(cx.sess(), stmt.kind.attrs(|id| cx.tcx.hir().item(id))) { if !has_attr(cx, stmt.hir_id) {
return; return;
} }
prelude(); prelude();
@ -139,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
} }
fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ForeignItem<'_>) { fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ForeignItem<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx, item.hir_id()) {
return; return;
} }
prelude(); prelude();
@ -719,8 +718,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
} }
} }
fn has_attr(sess: &Session, attrs: &[Attribute]) -> bool { fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
get_attr(sess, attrs, "author").count() > 0 let attrs = cx.tcx.hir().attrs(hir_id);
get_attr(cx.sess(), attrs, "author").count() > 0
} }
#[must_use] #[must_use]

View file

@ -33,14 +33,14 @@ declare_lint_pass!(DeepCodeInspector => [DEEP_CODE_INSPECTION]);
impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx.sess(), cx.tcx.hir().attrs(item.hir_id())) {
return; return;
} }
print_item(cx, item); print_item(cx, item);
} }
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
if !has_attr(cx.sess(), &item.attrs) { if !has_attr(cx.sess(), cx.tcx.hir().attrs(item.hir_id())) {
return; return;
} }
println!("impl item `{}`", item.ident.name); println!("impl item `{}`", item.ident.name);
@ -89,14 +89,14 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
// //
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if !has_attr(cx.sess(), &expr.attrs) { if !has_attr(cx.sess(), cx.tcx.hir().attrs(expr.hir_id)) {
return; return;
} }
print_expr(cx, expr, 0); print_expr(cx, expr, 0);
} }
fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) { fn check_arm(&mut self, cx: &LateContext<'tcx>, arm: &'tcx hir::Arm<'_>) {
if !has_attr(cx.sess(), &arm.attrs) { if !has_attr(cx.sess(), cx.tcx.hir().attrs(arm.hir_id)) {
return; return;
} }
print_pat(cx, &arm.pat, 1); print_pat(cx, &arm.pat, 1);
@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector {
} }
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) {
if !has_attr(cx.sess(), stmt.kind.attrs(|id| cx.tcx.hir().item(id))) { if !has_attr(cx.sess(), cx.tcx.hir().attrs(stmt.hir_id)) {
return; return;
} }
match stmt.kind { match stmt.kind {

View file

@ -61,7 +61,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::Node; use rustc_hir::Node;
use rustc_hir::{ use rustc_hir::{
def, Arm, Block, Body, Constness, Crate, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind, def, Arm, Block, Body, Constness, Expr, ExprKind, FnDecl, HirId, ImplItem, ImplItemKind, Item, ItemKind,
MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety, MatchSource, Param, Pat, PatKind, Path, PathSegment, QPath, TraitItem, TraitItemKind, TraitRef, TyKind, Unsafety,
}; };
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
@ -1510,8 +1510,8 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some()) did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some())
} }
pub fn is_no_std_crate(krate: &Crate<'_>) -> bool { pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
krate.item.attrs.iter().any(|attr| { cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
if let ast::AttrKind::Normal(ref attr, _) = attr.kind { if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
attr.path == sym::no_std attr.path == sym::no_std
} else { } else {