diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d9963f23a1593..bb6329dad4b9c 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -41,7 +41,7 @@ //! This order consistency is required in a few places in rustc, for //! example generator inference, and possibly also HIR borrowck. -use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute}; +use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name}; use syntax_pos::Span; use hir::*; use hir::def::Def; diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dc8baa112bb59..0733d5c6e176d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -483,7 +483,7 @@ impl<'a> LoweringContext<'a> { visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c); let module = self.lower_mod(&c.module); - let attrs = self.lower_attrs(&c.attrs); + let attrs = self.lower_attrs(&c.attrs).into(); let body_ids = body_ids(&self.bodies); self.resolver @@ -1057,21 +1057,32 @@ impl<'a> LoweringContext<'a> { } } - fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> { + fn lower_attrs(&mut self, attrs: &[Attribute]) -> Vec<hir::Attribute> { attrs .iter() .map(|a| self.lower_attr(a)) .collect() } - fn lower_attr(&mut self, attr: &Attribute) -> Attribute { - // 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 - // the HirIds. We don't actually need HIR version of attributes anyway. - Attribute { + fn lower_attr(&mut self, attr: &Attribute) -> hir::Attribute { + hir::Attribute { id: attr.id, style: attr.style, - path: attr.path.clone(), + // HACK(eddyb) manual conversion because `lower_path(_extra)` + // use `lower_path_segment` and that allocates `ItemLocalId`s. + path: hir::Path { + def: Def::Err, + segments: attr.path.segments.iter().map(|segment| { + hir::PathSegment::new( + segment.ident, + None, + None, + hir::GenericArgs::none(), + false, + ) + }).collect(), + span: attr.path.span, + }, tokens: self.lower_token_stream(attr.tokens.clone()), is_sugared_doc: attr.is_sugared_doc, span: attr.span, @@ -1110,7 +1121,7 @@ impl<'a> LoweringContext<'a> { fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { hir::Arm { - attrs: self.lower_attrs(&arm.attrs), + attrs: self.lower_attrs(&arm.attrs).into(), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), guard: match arm.guard { Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))), @@ -1576,7 +1587,7 @@ impl<'a> LoweringContext<'a> { Spanned { node: hir::VariantKind { name: v.node.ident.name, - attrs: self.lower_attrs(&v.node.attrs), + attrs: self.lower_attrs(&v.node.attrs).into(), data: self.lower_variant_data(&v.node.data), disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), }, @@ -1967,7 +1978,7 @@ impl<'a> LoweringContext<'a> { pat: self.lower_pat(&l.pat), init: l.init.as_ref().map(|e| P(self.lower_expr(e))), span: l.span, - attrs: l.attrs.clone(), + attrs: self.lower_attrs(&l.attrs).into(), source: hir::LocalSource::Normal, }), ids) } @@ -2410,7 +2421,7 @@ impl<'a> LoweringContext<'a> { name: param_name, span: lt.span, pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), - attrs: self.lower_attrs(¶m.attrs), + attrs: self.lower_attrs(¶m.attrs).into(), bounds, kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit, @@ -2443,7 +2454,7 @@ impl<'a> LoweringContext<'a> { id: self.lower_node_id(param.id).node_id, name: hir::ParamName::Plain(ident), pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), - attrs: self.lower_attrs(¶m.attrs), + attrs: self.lower_attrs(¶m.attrs).into(), bounds, span: ident.span, kind: hir::GenericParamKind::Type { @@ -2667,7 +2678,7 @@ impl<'a> LoweringContext<'a> { }, vis: self.lower_visibility(&f.vis, None), ty: self.lower_ty(&f.ty, ImplTraitContext::disallowed()), - attrs: self.lower_attrs(&f.attrs), + attrs: self.lower_attrs(&f.attrs).into(), } } @@ -2750,7 +2761,7 @@ impl<'a> LoweringContext<'a> { &mut self, id: NodeId, name: &mut Name, - attrs: &hir::HirVec<Attribute>, + attrs: &hir::HirVec<hir::Attribute>, vis: &mut hir::Visibility, i: &ItemKind, ) -> hir::ItemKind { @@ -2956,7 +2967,7 @@ impl<'a> LoweringContext<'a> { id: NodeId, vis: &mut hir::Visibility, name: &mut Name, - attrs: &hir::HirVec<Attribute>, + attrs: &hir::HirVec<hir::Attribute>, ) -> hir::ItemKind { debug!("lower_use_tree(tree={:?})", tree); debug!("lower_use_tree: vis = {:?}", vis); @@ -3257,7 +3268,7 @@ impl<'a> LoweringContext<'a> { id: node_id, hir_id, ident: i.ident, - attrs: self.lower_attrs(&i.attrs), + attrs: self.lower_attrs(&i.attrs).into(), generics, node, span: i.span, @@ -3333,7 +3344,7 @@ impl<'a> LoweringContext<'a> { id: node_id, hir_id, ident: i.ident, - attrs: self.lower_attrs(&i.attrs), + attrs: self.lower_attrs(&i.attrs).into(), generics, vis: self.lower_visibility(&i.vis, None), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), @@ -3427,7 +3438,7 @@ impl<'a> LoweringContext<'a> { pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> { let mut name = i.ident.name; let mut vis = self.lower_visibility(&i.vis, None); - let attrs = self.lower_attrs(&i.attrs); + let attrs = self.lower_attrs(&i.attrs).into(); if let ItemKind::MacroDef(ref def) = i.node { if !def.legacy || attr::contains_name(&i.attrs, "macro_export") || attr::contains_name(&i.attrs, "rustc_doc_only_macro") { @@ -3466,7 +3477,7 @@ impl<'a> LoweringContext<'a> { hir::ForeignItem { id: node_id, name: i.ident.name, - attrs: self.lower_attrs(&i.attrs), + attrs: self.lower_attrs(&i.attrs).into(), node: match i.node { ForeignItemKind::Fn(ref fdec, ref generics) => { let (generics, (fn_dec, fn_args)) = self.add_in_band_defs( @@ -4025,7 +4036,7 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Struct(struct_path, fields, None) }, span: e.span, - attrs: e.attrs.clone(), + attrs: self.lower_attrs(&e.attrs).into(), }; } ExprKind::Path(ref qself, ref path) => { @@ -4111,7 +4122,7 @@ impl<'a> LoweringContext<'a> { ex.span = e.span; } // merge attributes into the inner expression. - let mut attrs = e.attrs.clone(); + let mut attrs: ThinVec<_> = self.lower_attrs(&e.attrs).into(); attrs.extend::<Vec<_>>(ex.attrs.into()); ex.attrs = attrs; return ex; @@ -4394,7 +4405,8 @@ impl<'a> LoweringContext<'a> { let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding)); let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result))); // add the attributes to the outer returned expr node - return self.expr_block(block, e.attrs.clone()); + let attrs = self.lower_attrs(&e.attrs).into(); + return self.expr_block(block, attrs); } // Desugar ExprKind::Try @@ -4507,7 +4519,7 @@ impl<'a> LoweringContext<'a> { hir_id, node: kind, span: e.span, - attrs: e.attrs.clone(), + attrs: self.lower_attrs(&e.attrs).into(), } } @@ -4685,7 +4697,7 @@ impl<'a> LoweringContext<'a> { } } - fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> { + fn expr_break(&mut self, span: Span, attrs: ThinVec<hir::Attribute>) -> P<hir::Expr> { let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None); P(self.expr(span, expr_break, attrs)) } @@ -4708,7 +4720,7 @@ impl<'a> LoweringContext<'a> { span: Span, ident: Ident, binding: NodeId, - attrs: ThinVec<Attribute>, + attrs: ThinVec<hir::Attribute>, ) -> hir::Expr { let expr_path = hir::ExprKind::Path(hir::QPath::Resolved( None, @@ -4731,7 +4743,7 @@ impl<'a> LoweringContext<'a> { span: Span, components: &[&str], params: Option<P<hir::GenericArgs>>, - attrs: ThinVec<Attribute>, + attrs: ThinVec<hir::Attribute>, ) -> hir::Expr { let path = self.std_path(span, components, params, true); self.expr( @@ -4751,7 +4763,7 @@ impl<'a> LoweringContext<'a> { self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new()) } - fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr { + fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<hir::Attribute>) -> hir::Expr { self.expr(b.span, hir::ExprKind::Block(b, None), attrs) } @@ -4759,7 +4771,12 @@ impl<'a> LoweringContext<'a> { P(self.expr(sp, hir::ExprKind::Tup(exprs), ThinVec::new())) } - fn expr(&mut self, span: Span, node: hir::ExprKind, attrs: ThinVec<Attribute>) -> hir::Expr { + fn expr( + &mut self, + span: Span, + node: hir::ExprKind, + attrs: ThinVec<hir::Attribute>, + ) -> hir::Expr { let LoweredNodeId { node_id, hir_id } = self.next_id(); hir::Expr { id: node_id, diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 1ab1c7d3fc5c4..5cb0b4017458a 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -23,9 +23,9 @@ use hir as ast; use hir::map; -use hir::{Expr, FnDecl, Node}; +use hir::{Attribute, Expr, FnDecl, Node}; use hir::intravisit::FnKind; -use syntax::ast::{Attribute, Ident, Name, NodeId}; +use syntax::ast::{Ident, Name, NodeId}; use syntax_pos::Span; /// An FnLikeNode is a Node that is like a fn, in that it has a decl diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ef777abfbc41a..e3dac03ca2b38 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -504,7 +504,7 @@ impl<'hir> Map<'hir> { /// Get the attributes on the krate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. - pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { + pub fn krate_attrs(&self) -> &'hir [Attribute] { let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); @@ -834,7 +834,7 @@ impl<'hir> Map<'hir> { /// Given a node ID, get a list of attributes associated with the AST /// corresponding to the Node ID - pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] { + pub fn attrs(&self, id: NodeId) -> &'hir [Attribute] { self.read(id); // reveals attributes on the node let attrs = match self.find(id) { Some(Node::Item(i)) => Some(&i.attrs[..]), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1674320165e65..194c09386d1ec 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -27,8 +27,8 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy}; -use syntax::attr::InlineAttr; +use syntax::ast::{Lit, StrStyle, FloatTy, IntTy, UintTy}; +use syntax::attr::{self, InlineAttr}; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; @@ -150,6 +150,12 @@ pub const DUMMY_HIR_ID: HirId = HirId { pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; +pub type Attribute = ast::Attribute<Path>; +pub type MetaItem = ast::MetaItem<Path>; +pub type MetaItemKind = ast::MetaItemKind<Path>; +pub type NestedMetaItem = ast::NestedMetaItem<Path>; +pub type NestedMetaItemKind = ast::NestedMetaItemKind<Path>; + #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Label { pub ident: Ident, @@ -327,6 +333,34 @@ impl fmt::Display for Path { } } +impl attr::Path for Path { + type Segment = PathSegment; + + fn from_span_and_segments(span: Span, segments: Vec<Self::Segment>) -> Self { + Self { + span, + def: Def::Err, + segments: HirVec::from(segments), + } + } + + fn from_nt( + _: &::syntax::parse::token::Nonterminal, + ) -> Result<Self, Option<ast::MetaItem<Self>>> { + bug!("interpolated tokens should not be present in the HIR") + } + + #[inline] + fn span(&self) -> Span { + self.span + } + + #[inline] + fn segments(&self) -> &[Self::Segment] { + &self.segments + } +} + /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -401,6 +435,17 @@ impl PathSegment { } } +impl attr::PathSegment for PathSegment { + fn from_ident(ident: Ident) -> Self { + Self::from_ident(ident) + } + + #[inline] + fn ident(&self) -> Ident { + self.ident + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum GenericArg { Lifetime(Lifetime), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9a0ceddcf1b4a..985d1e8583d25 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -339,7 +339,7 @@ impl<'a> State<'a> { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) } - pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> { + pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[hir::Attribute]) -> io::Result<()> { self.print_inner_attributes(attrs)?; for &item_id in &_mod.item_ids { self.ann.nested(self, Nested::Item(item_id))?; @@ -349,7 +349,7 @@ impl<'a> State<'a> { pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod, - attrs: &[ast::Attribute]) + attrs: &[hir::Attribute]) -> io::Result<()> { self.print_inner_attributes(attrs)?; for item in &nmod.items { @@ -1035,7 +1035,7 @@ impl<'a> State<'a> { pub fn print_block_with_attrs(&mut self, blk: &hir::Block, - attrs: &[ast::Attribute]) + attrs: &[hir::Attribute]) -> io::Result<()> { self.print_block_maybe_unclosed(blk, indent_unit, attrs, true) } @@ -1043,7 +1043,7 @@ impl<'a> State<'a> { pub fn print_block_maybe_unclosed(&mut self, blk: &hir::Block, indented: usize, - attrs: &[ast::Attribute], + attrs: &[hir::Attribute], close_box: bool) -> io::Result<()> { match blk.rules { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index ae0d78d2958ad..f8c13c92a275c 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -17,6 +17,7 @@ use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; use ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; +use smallvec::SmallVec; use std::mem; use syntax::ast; use syntax::attr; @@ -1197,3 +1198,91 @@ impl_stable_hash_for!(struct hir::Freevar { def, span }); + +impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + if self.len() == 0 { + self.len().hash_stable(hcx, hasher); + return + } + + // Some attributes are always ignored during hashing. + let filtered: SmallVec<[&hir::Attribute; 8]> = self + .iter() + .filter(|attr| { + !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name()) + }) + .collect(); + + filtered.len().hash_stable(hcx, hasher); + for attr in filtered { + attr.hash_stable(hcx, hasher); + } + } +} + +impl<'a> HashStable<StableHashingContext<'a>> for hir::Attribute { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + // Make sure that these have been filtered out. + debug_assert!(!hcx.is_ignored_attr(self.name())); + debug_assert!(!self.is_sugared_doc); + + let hir::Attribute { + id: _, + style, + ref path, + ref tokens, + is_sugared_doc: _, + span, + } = *self; + + style.hash_stable(hcx, hasher); + path.hash_stable(hcx, hasher); + for tt in tokens.trees() { + tt.hash_stable(hcx, hasher); + } + span.hash_stable(hcx, hasher); + } +} +impl_stable_hash_for_spanned!(hir::NestedMetaItemKind); + +// HACK(eddyb) need manual impl because `hir::NestedMetaItemKind` is an alias. +impl<'a> HashStable<StableHashingContext<'a>> for hir::NestedMetaItemKind { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + use syntax::ast::NestedMetaItemKind::*; + + mem::discriminant(self).hash_stable(hcx, hasher); + match self { + MetaItem(meta_item) => meta_item.hash_stable(hcx, hasher), + Literal(lit) => lit.hash_stable(hcx, hasher), + } + } +} + +impl_stable_hash_for!(struct hir::MetaItem { + ident, + node, + span +}); + +// HACK(eddyb) need manual impl because `hir::MetaItemKind` is an alias. +impl<'a> HashStable<StableHashingContext<'a>> for hir::MetaItemKind { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>) { + use syntax::ast::MetaItemKind::*; + + mem::discriminant(self).hash_stable(hcx, hasher); + match self { + Word => {} + List(nested_items) => nested_items.hash_stable(hcx, hasher), + NameValue(lit) => lit.hash_stable(hcx, hasher), + } + } +} diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 4be467c01aac1..353da1aed7bd1 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -25,7 +25,6 @@ use syntax_pos::SourceFile; use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; -use smallvec::SmallVec; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; @@ -197,67 +196,6 @@ impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident }); impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) }); impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner }); -impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher<W>) { - if self.len() == 0 { - self.len().hash_stable(hcx, hasher); - return - } - - // Some attributes are always ignored during hashing. - let filtered: SmallVec<[&ast::Attribute; 8]> = self - .iter() - .filter(|attr| { - !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name()) - }) - .collect(); - - filtered.len().hash_stable(hcx, hasher); - for attr in filtered { - attr.hash_stable(hcx, hasher); - } - } -} - -impl<'a> HashStable<StableHashingContext<'a>> for ast::Path { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher<W>) { - self.segments.len().hash_stable(hcx, hasher); - for segment in &self.segments { - segment.ident.name.hash_stable(hcx, hasher); - } - } -} - -impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute { - fn hash_stable<W: StableHasherResult>(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher<W>) { - // Make sure that these have been filtered out. - debug_assert!(!hcx.is_ignored_attr(self.name())); - debug_assert!(!self.is_sugared_doc); - - let ast::Attribute { - id: _, - style, - ref path, - ref tokens, - is_sugared_doc: _, - span, - } = *self; - - style.hash_stable(hcx, hasher); - path.hash_stable(hcx, hasher); - for tt in tokens.trees() { - tt.hash_stable(hcx, hasher); - } - span.hash_stable(hcx, hasher); - } -} - impl<'a> HashStable<StableHashingContext<'a>> for tokenstream::TokenTree { fn hash_stable<W: StableHasherResult>(&self, @@ -372,25 +310,6 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>( } } -impl_stable_hash_for_spanned!(::syntax::ast::NestedMetaItemKind); - -impl_stable_hash_for!(enum ::syntax::ast::NestedMetaItemKind { - MetaItem(meta_item), - Literal(lit) -}); - -impl_stable_hash_for!(struct ::syntax::ast::MetaItem { - ident, - node, - span -}); - -impl_stable_hash_for!(enum ::syntax::ast::MetaItemKind { - Word, - List(nested_items), - NameValue(lit) -}); - impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { call_site, def_site, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 469d77403a3d8..f7d20747104b8 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -549,13 +549,14 @@ impl LintPassObject for LateLintPassObject {} pub trait LintContext<'tcx>: Sized { type PassObject: LintPassObject; + type Path; fn sess(&self) -> &Session; fn lints(&self) -> &LintStore; fn lint_sess(&self) -> &LintSession<'tcx, Self::PassObject>; fn lint_sess_mut(&mut self) -> &mut LintSession<'tcx, Self::PassObject>; - fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]); - fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]); + fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute<Self::Path>]); + fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute<Self::Path>]); fn lookup_and_emit<S: Into<MultiSpan>>(&self, lint: &'static Lint, @@ -624,7 +625,7 @@ pub trait LintContext<'tcx>: Sized { /// lints in effect to their previous state. fn with_lint_attrs<F>(&mut self, id: ast::NodeId, - attrs: &'tcx [ast::Attribute], + attrs: &'tcx [ast::Attribute<Self::Path>], f: F) where F: FnOnce(&mut Self); } @@ -661,6 +662,7 @@ impl<'a> EarlyContext<'a> { impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { type PassObject = LateLintPassObject; + type Path = hir::Path; /// Get the overall compiler `Session` object. fn sess(&self) -> &Session { @@ -679,12 +681,12 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { &mut self.lint_sess } - fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { + fn enter_attrs(&mut self, attrs: &'tcx [hir::Attribute]) { debug!("late context: enter_attrs({:?})", attrs); run_lints!(self, enter_lint_attrs, attrs); } - fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { + fn exit_attrs(&mut self, attrs: &'tcx [hir::Attribute]) { debug!("late context: exit_attrs({:?})", attrs); run_lints!(self, exit_lint_attrs, attrs); } @@ -703,7 +705,7 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { fn with_lint_attrs<F>(&mut self, id: ast::NodeId, - attrs: &'tcx [ast::Attribute], + attrs: &'tcx [hir::Attribute], f: F) where F: FnOnce(&mut Self) { @@ -718,6 +720,7 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { impl<'a> LintContext<'a> for EarlyContext<'a> { type PassObject = EarlyLintPassObject; + type Path = ast::Path; /// Get the overall compiler `Session` object. fn sess(&self) -> &Session { @@ -997,7 +1000,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_path(self, p); } - fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) { + fn visit_attribute(&mut self, attr: &'tcx hir::Attribute) { run_lints!(self, check_attribute, attr); } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index cfb9f04c4c6d1..351a432ea09ba 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -195,7 +195,7 @@ impl<'a> LintLevelsBuilder<'a> { /// #[allow] /// /// Don't forget to call `pop`! - pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { + pub fn push(&mut self, attrs: &[ast::Attribute<impl attr::Path>]) -> BuilderPush { let mut specs = FxHashMap::default(); let store = self.sess.lint_store.borrow(); let sess = self.sess; @@ -233,7 +233,7 @@ impl<'a> LintLevelsBuilder<'a> { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { let gate_reasons = !self.sess.features_untracked().lint_reasons; - if item.ident == "reason" { + if item.check_name_correct("reason") { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; // FIXME (#55112): issue unused-attributes lint if we thereby @@ -274,7 +274,7 @@ impl<'a> LintLevelsBuilder<'a> { let mut err = bad_attr(li.span); if let Some(item) = li.meta_item() { if let ast::MetaItemKind::NameValue(_) = item.node { - if item.ident == "reason" { + if item.check_name_correct("reason") { err.help("reason in lint attribute must come last"); } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 4b878b862526b..38e378e24d887 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -243,14 +243,14 @@ macro_rules! late_lint_methods { fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics); fn check_lifetime(a: &$hir hir::Lifetime); fn check_path(a: &$hir hir::Path, b: hir::HirId); - fn check_attribute(a: &$hir ast::Attribute); + fn check_attribute(a: &$hir hir::Attribute); /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. - fn enter_lint_attrs(a: &$hir [ast::Attribute]); + fn enter_lint_attrs(a: &$hir [hir::Attribute]); /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(a: &$hir [ast::Attribute]); + fn exit_lint_attrs(a: &$hir [hir::Attribute]); ]); ) } @@ -660,7 +660,7 @@ struct LintLevelMapBuilder<'a, 'tcx: 'a> { impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> { fn with_lint_attrs<F>(&mut self, id: ast::NodeId, - attrs: &[ast::Attribute], + attrs: &[hir::Attribute], f: F) where F: FnOnce(&mut Self) { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4720bb2954963..9bc6e31910c7f 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,6 +22,7 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. +use hir; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::definitions::{DefKey, DefPathTable}; @@ -121,7 +122,7 @@ pub enum NativeLibraryKind { pub struct NativeLibrary { pub kind: NativeLibraryKind, pub name: Option<Symbol>, - pub cfg: Option<ast::MetaItem>, + pub cfg: Option<hir::MetaItem>, pub foreign_module: Option<DefId>, pub wasm_import_module: Option<Symbol>, } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 282b5d13e2c61..15c5a58c4f23c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -286,7 +286,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>, id: ast::NodeId, - attrs: &[ast::Attribute]) -> bool { + attrs: &[hir::Attribute]) -> bool { if attr::contains_name(attrs, "lang") { return true; } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index e7a8baf738395..e45203ace03eb 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -27,7 +27,6 @@ use ty::{self, TyCtxt}; use middle::weak_lang_items; use util::nodemap::FxHashMap; -use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use hir::itemlikevisit::ItemLikeVisitor; @@ -198,7 +197,7 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { } } -pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { +pub fn extract(attrs: &[hir::Attribute]) -> Option<(Symbol, Span)> { for attribute in attrs { if attribute.check_name("lang") { if let Some(value) = attribute.value_str() { diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 7d65d412e01d7..ff580ccdf7706 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -16,8 +16,9 @@ use ty::TyCtxt; use syntax::symbol::Symbol; -use syntax::ast::{Attribute, MetaItem, MetaItemKind}; +use syntax::ast::{MetaItem, MetaItemKind}; use syntax_pos::Span; +use hir::Attribute; use hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use errors::DiagnosticId; diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 543d1053b55e6..4a1dc43ce5aee 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -22,13 +22,13 @@ use session::{DiagnosticMessageId, Session}; use syntax::symbol::Symbol; use syntax_pos::{Span, MultiSpan}; use syntax::ast; -use syntax::ast::{NodeId, Attribute}; +use syntax::ast::NodeId; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::attr::{self, Stability, Deprecation}; use util::nodemap::{FxHashSet, FxHashMap}; use hir; -use hir::{Item, Generics, StructField, Variant, HirId}; +use hir::{Attribute, Item, Generics, StructField, Variant, HirId}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use std::mem::replace; diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 0d407765c9e10..ebf01660ff7b3 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -15,7 +15,6 @@ use middle::lang_items; use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::PanicStrategy; -use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use hir::def_id::DefId; @@ -54,7 +53,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, verify(tcx, items); } -pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> { +pub fn link_name(attrs: &[hir::Attribute]) -> Option<Symbol> { lang_items::extract(attrs).and_then(|(name, _)| { $(if name == stringify!($name) { Some(Symbol::intern(stringify!($sym))) diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index dcbddc0308091..2a35aff9265d3 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -15,7 +15,7 @@ use ty::{self, TyCtxt, GenericParamDefKind}; use util::common::ErrorReported; use util::nodemap::FxHashMap; -use syntax::ast::{MetaItem, NestedMetaItem}; +use hir::{MetaItem, NestedMetaItem}; use syntax::attr; use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4633ab1166347..399c576ccd0a9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2602,14 +2602,14 @@ impl BorrowKind { #[derive(Debug, Clone)] pub enum Attributes<'gcx> { - Owned(Lrc<[ast::Attribute]>), - Borrowed(&'gcx [ast::Attribute]) + Owned(Lrc<[hir::Attribute]>), + Borrowed(&'gcx [hir::Attribute]) } impl<'gcx> ::std::ops::Deref for Attributes<'gcx> { - type Target = [ast::Attribute]; + type Target = [hir::Attribute]; - fn deref(&self) -> &[ast::Attribute] { + fn deref(&self) -> &[hir::Attribute] { match self { &Attributes::Owned(ref data) => &data, &Attributes::Borrowed(data) => data diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 699c2d111c639..fc6ef43ddbc6b 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -341,7 +341,7 @@ define_queries! { <'tcx> [] fn def_span: DefSpan(DefId) -> Span, [] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>, [] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>, - [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>, + [] fn item_attrs: ItemAttrs(DefId) -> Lrc<[hir::Attribute]>, }, Codegen { diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index b11aa687326f2..0430fc04cd482 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -48,7 +48,7 @@ fn is_writeable(p: &Path) -> bool { } pub fn find_crate_name(sess: Option<&Session>, - attrs: &[ast::Attribute], + attrs: &[ast::Attribute<impl attr::Path>], input: &Input) -> String { let validate = |s: String, span: Option<Span>| { ::rustc_metadata::validate_crate_name(sess, &s, span); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 22a0cc983daab..e0cedd648174e 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -106,7 +106,7 @@ struct IfThisChanged<'a, 'tcx:'a> { } impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { - fn argument(&self, attr: &ast::Attribute) -> Option<ast::Name> { + fn argument(&self, attr: &hir::Attribute) -> Option<ast::Name> { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { match list_item.word() { @@ -120,7 +120,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { value } - fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { + fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[hir::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); let def_path_hash = self.tcx.def_path_hash(def_id); for attr in attrs { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 4ff2529b26d93..fe364d03d9937 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -31,6 +31,7 @@ //! allows for doing a more fine-grained check to see if pre- or post-lto data //! was re-used. +use rustc::hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::dep_graph::cgu_reuse_tracker::*; use rustc::mir::mono::CodegenUnitNameBuilder; @@ -74,7 +75,7 @@ struct AssertModuleSource<'a, 'tcx: 'a> { } impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { - fn check_attr(&self, attr: &ast::Attribute) { + fn check_attr(&self, attr: &hir::Attribute) { let (expected_reuse, comp_kind) = if attr.check_name(ATTR_PARTITION_REUSED) { (CguReuse::PreLto, ComparisonKind::AtLeast) } else if attr.check_name(ATTR_PARTITION_CODEGENED) { @@ -156,7 +157,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { comp_kind); } - fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name { + fn field(&self, attr: &hir::Attribute, name: &str) -> ast::Name { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.check_name(name) { if let Some(value) = item.value_str() { @@ -176,7 +177,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { /// Scan for a `cfg="foo"` attribute and check whether we have a /// cfg flag called `foo`. - fn check_config(&self, attr: &ast::Attribute) -> bool { + fn check_config(&self, attr: &hir::Attribute) -> bool { let config = &self.tcx.sess.parse_sess.config; let value = self.field(attr, CFG); debug!("check_config(config={:?}, value={:?})", config, value); diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index f76086139ed7e..ed71ffe068d31 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -28,13 +28,13 @@ use std::iter::FromIterator; use std::vec::Vec; use rustc::dep_graph::{DepNode, label_strs}; use rustc::hir; -use rustc::hir::{ItemKind as HirItem, ImplItemKind, TraitItemKind}; +use rustc::hir::{Attribute, NestedMetaItem, ItemKind as HirItem, ImplItemKind, TraitItemKind}; use rustc::hir::Node as HirNode; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; -use syntax::ast::{self, Attribute, NestedMetaItem}; +use syntax::ast; use rustc_data_structures::fx::FxHashSet; use syntax_pos::Span; use rustc::ty::TyCtxt; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7dd1ca3493e9d..22938ac6ef87f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -322,7 +322,7 @@ impl MissingDoc { fn check_missing_docs_attrs(&self, cx: &LateContext, id: Option<ast::NodeId>, - attrs: &[ast::Attribute], + attrs: &[hir::Attribute], sp: Span, desc: &'static str) { // If we're building a test harness, then warning about @@ -345,7 +345,7 @@ impl MissingDoc { } } - fn has_doc(attr: &ast::Attribute) -> bool { + fn has_doc(attr: &hir::Attribute) -> bool { if !attr.check_name("doc") { return false; } @@ -381,7 +381,7 @@ impl LintPass for MissingDoc { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { - fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) { + fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[hir::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name("doc") && @@ -393,7 +393,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &LateContext, _attrs: &[ast::Attribute]) { + fn exit_lint_attrs(&mut self, _: &LateContext, _attrs: &[hir::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } @@ -1043,7 +1043,7 @@ impl LintPass for UnstableFeatures { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { - fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) { + fn check_attribute(&mut self, ctx: &LateContext, attr: &hir::Attribute) { if attr.check_name("feature") { if let Some(items) = attr.meta_item_list() { for item in items { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index fab618d9c8ec8..9055208a83ca8 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -239,7 +239,7 @@ impl LintPass for UnusedAttributes { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { - fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext, attr: &hir::Attribute) { debug!("checking attribute: {:?}", attr); // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty, _) in BUILTIN_ATTRIBUTES { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d0fa63a6163db..74bb319cc97fc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -463,7 +463,33 @@ impl cstore::CStore { ident: ast::Ident::from_str(&name.as_str()), id: ast::DUMMY_NODE_ID, span: local_span, - attrs: attrs.iter().cloned().collect(), + attrs: attrs.iter().map(|attr| { + // HACK(eddyb) convert from a `hir::Attribute` to an `ast::Attribute` + // (ideally we wouldn't need to create a fake `ast::Item`) + let ast::Attribute { + id, + style, + ref path, + ref tokens, + is_sugared_doc, + span, + } = *attr; + ast::Attribute { + id, + style, + path: ast::Path { + span: path.span, + segments: path.segments.iter().map(|segment| ast::PathSegment { + ident: segment.ident, + id: ast::DUMMY_NODE_ID, + args: None, + }).collect(), + }, + tokens: tokens.clone(), + is_sugared_doc, + span, + } + }).collect(), node: ast::ItemKind::MacroDef(ast::MacroDef { tokens: body.into(), legacy: def.legacy, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1c7e3c95d1470..7f652745a988b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -926,7 +926,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { + pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[hir::Attribute]> { if self.is_proc_macro(node_id) { return Lrc::new([]); } @@ -953,7 +953,7 @@ impl<'a, 'tcx> CrateMetadata { .collect() } - fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> { + fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<hir::Attribute> { item.attributes .decode((self, sess)) .map(|mut attr| { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2736c60ffb6fa..0f53a970a4468 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -632,7 +632,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, - &[ast::Attribute], + &[hir::Attribute], &hir::Visibility)>) -> Entry<'tcx> { let tcx = self.tcx; @@ -1407,7 +1407,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> { + fn encode_attributes(&mut self, attrs: &[hir::Attribute]) -> LazySeq<hir::Attribute> { // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because // we rely on the HashStable specialization for [Attribute] // to properly filter things out. diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 008e1e363ff53..fa7f191f9f55e 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -20,7 +20,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<String> { tcx.hir.krate().visit_all_item_likes(&mut collector); for attr in tcx.hir.krate().attrs.iter() { - if attr.path == "link_args" { + if attr.check_name("link_args") { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index e91d15b78c075..133b036bdea94 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -265,7 +265,7 @@ pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: Lazy<ty::Visibility>, pub span: Lazy<Span>, - pub attributes: LazySeq<ast::Attribute>, + pub attributes: LazySeq<hir::Attribute>, pub children: LazySeq<DefIndex>, pub stability: Option<Lazy<attr::Stability>>, pub deprecation: Option<Lazy<attr::Deprecation>>, diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index c19145636e6da..0fbe225496bb1 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{self, MetaItem}; +use syntax::ast; use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; +use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::mir::traversal; @@ -100,7 +101,7 @@ impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> where BD: fn propagate(&mut self) { self.flow_state.propagate(); } } -pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> { +pub(crate) fn has_rustc_mir_with(attrs: &[hir::Attribute], name: &str) -> Option<hir::MetaItem> { for attr in attrs { if attr.check_name("rustc_mir") { let items = attr.meta_item_list(); @@ -123,7 +124,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> { pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, node_id: ast::NodeId, - attributes: &[ast::Attribute], + attributes: &[hir::Attribute], dead_unwinds: &BitSet<BasicBlock>, bd: BD, p: P) @@ -140,11 +141,11 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD pub(crate) fn run<P>(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, node_id: ast::NodeId, - attributes: &[ast::Attribute], + attributes: &[hir::Attribute], p: P) -> DataflowResults<BD> where P: Fn(&BD, BD::Idx) -> DebugFormatted { - let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> { + let name_found = |sess: &Session, attrs: &[hir::Attribute], name| -> Option<String> { if let Some(item) = has_rustc_mir_with(attrs, name) { if let Some(s) = item.value_str() { return Some(s.to_string()) diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index f852195b8351a..a92ead0e59121 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -12,6 +12,7 @@ use rustc_target::spec::abi::{Abi}; use syntax::ast; use syntax_pos::Span; +use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bit_set::BitSet; @@ -94,7 +95,7 @@ impl MirPass for SanityCheck { pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, id: ast::NodeId, - _attributes: &[ast::Attribute], + _attributes: &[hir::Attribute], results: &DataflowResults<O>) where O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx> { diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 019fb9565f413..eb6654524d937 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -253,7 +253,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_assoc_type_binding(self, type_binding) } - fn visit_attribute(&mut self, attr: &'v ast::Attribute) { + fn visit_attribute(&mut self, attr: &'v hir::Attribute) { self.record("Attribute", Id::Attr(attr.id), attr); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 82c4795a29d4b..80ecb1e9e2029 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -57,6 +57,7 @@ use std::env; use std::fs::File; use std::path::{Path, PathBuf}; +use syntax::attr; use syntax::ast::{self, Attribute, DUMMY_NODE_ID, NodeId, PatKind}; use syntax::source_map::Spanned; use syntax::parse::lexer::comments::strip_doc_comment_decoration; @@ -892,7 +893,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - fn docs_for_attrs(&self, attrs: &[Attribute]) -> String { + fn docs_for_attrs(&self, attrs: &[Attribute<impl attr::Path>]) -> String { let mut result = String::new(); for attr in attrs { @@ -1202,10 +1203,13 @@ fn null_id() -> rls_data::Id { } } -fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext) -> Vec<rls_data::Attribute> { +fn lower_attributes( + attrs: Vec<Attribute<impl attr::Path>>, + scx: &SaveContext, +) -> Vec<rls_data::Attribute> { attrs.into_iter() // Only retain real attributes. Doc comments are lowered separately. - .filter(|attr| attr.path != "doc") + .filter(|attr| !attr.check_name("doc")) .map(|mut attr| { // Remove the surrounding '#[..]' or '#![..]' of the pretty printed // attribute. First normalize all inner attribute (#![..]) to outer diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 2d8e5b48aac7b..f34236024078f 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -625,7 +625,7 @@ struct ClauseDumper<'a, 'tcx: 'a> { } impl<'a, 'tcx> ClauseDumper<'a, 'tcx> { - fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) { + fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[hir::Attribute]) { let def_id = self.tcx.hir.local_def_id(node_id); for attr in attrs { let mut clauses = None; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a1bb0b53f1fce..537f3082de9e3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -44,7 +44,7 @@ use rustc_target::spec::abi; use syntax::ast; use syntax::ast::MetaItemKind; -use syntax::attr::{InlineAttr, list_contains_name, mark_used}; +use syntax::attr::{InlineAttr, list_contains_name}; use syntax::source_map::Spanned; use syntax::feature_gate; use syntax::symbol::{keywords, Symbol}; @@ -2137,7 +2137,7 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool fn from_target_feature( tcx: TyCtxt, id: DefId, - attr: &ast::Attribute, + attr: &hir::Attribute, whitelist: &FxHashMap<String, Option<String>>, target_features: &mut Vec<Symbol>, ) { @@ -2290,48 +2290,41 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen } else if attr.check_name("thread_local") { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.check_name("inline") { - codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { - if attr.path != "inline" { - return ia; + let meta = match attr.meta() { + Some(meta) => meta.node, + None => continue, + }; + match meta { + MetaItemKind::Word => { + codegen_fn_attrs.inline = InlineAttr::Hint; } - let meta = match attr.meta() { - Some(meta) => meta.node, - None => return ia, - }; - match meta { - MetaItemKind::Word => { - mark_used(attr); - InlineAttr::Hint - } - MetaItemKind::List(ref items) => { - mark_used(attr); - inline_span = Some(attr.span); - if items.len() != 1 { - span_err!( - tcx.sess.diagnostic(), - attr.span, - E0534, - "expected one argument" - ); - InlineAttr::None - } else if list_contains_name(&items[..], "always") { - InlineAttr::Always - } else if list_contains_name(&items[..], "never") { - InlineAttr::Never - } else { - span_err!( - tcx.sess.diagnostic(), - items[0].span, - E0535, - "invalid argument" - ); + MetaItemKind::List(ref items) => { + inline_span = Some(attr.span); + codegen_fn_attrs.inline = if items.len() != 1 { + span_err!( + tcx.sess.diagnostic(), + attr.span, + E0534, + "expected one argument" + ); + InlineAttr::None + } else if list_contains_name(&items[..], "always") { + InlineAttr::Always + } else if list_contains_name(&items[..], "never") { + InlineAttr::Never + } else { + span_err!( + tcx.sess.diagnostic(), + items[0].span, + E0535, + "invalid argument" + ); - InlineAttr::None - } - } - _ => ia, + InlineAttr::None + }; } - }); + _ => {} + } } else if attr.check_name("export_name") { if let Some(s) = attr.value_str() { if s.as_str().contains("\0") { diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index f90f1e54da22c..42deb84cb8e6d 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -18,6 +18,7 @@ use std::ops; use syntax::symbol::Symbol; use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, LitKind}; +use syntax::attr; use syntax::parse::ParseSess; use syntax::feature_gate::Features; @@ -49,7 +50,7 @@ pub struct InvalidCfgError { impl Cfg { /// Parses a `NestedMetaItem` into a `Cfg`. - fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> { + fn parse_nested(nested_cfg: &NestedMetaItem<impl attr::Path>) -> Result<Cfg, InvalidCfgError> { match nested_cfg.node { NestedMetaItemKind::MetaItem(ref cfg) => Cfg::parse(cfg), NestedMetaItemKind::Literal(ref lit) => Err(InvalidCfgError { @@ -66,7 +67,7 @@ impl Cfg { /// /// If the content is not properly formatted, it will return an error indicating what and where /// the error is. - pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> { + pub fn parse(cfg: &MetaItem<impl attr::Path>) -> Result<Cfg, InvalidCfgError> { let name = cfg.name(); match cfg.node { MetaItemKind::Word => Ok(Cfg::Cfg(name, None)), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fd8f70b19e7ec..d946dedfa5053 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -639,13 +639,13 @@ impl Clean<Item> for doctree::Module { } pub struct ListAttributesIter<'a> { - attrs: slice::Iter<'a, ast::Attribute>, - current_list: vec::IntoIter<ast::NestedMetaItem>, + attrs: slice::Iter<'a, hir::Attribute>, + current_list: vec::IntoIter<hir::NestedMetaItem>, name: &'a str } impl<'a> Iterator for ListAttributesIter<'a> { - type Item = ast::NestedMetaItem; + type Item = hir::NestedMetaItem; fn next(&mut self) -> Option<Self::Item> { if let Some(nested) = self.current_list.next() { @@ -677,7 +677,7 @@ pub trait AttributesExt { fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>; } -impl AttributesExt for [ast::Attribute] { +impl AttributesExt for [hir::Attribute] { fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { ListAttributesIter { attrs: self.iter(), @@ -692,7 +692,7 @@ pub trait NestedAttributesExt { fn has_word(self, word: &str) -> bool; } -impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I { +impl<I: IntoIterator<Item=hir::NestedMetaItem>> NestedAttributesExt for I { fn has_word(self, word: &str) -> bool { self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) } @@ -761,7 +761,7 @@ impl<'a> FromIterator<&'a DocFragment> for String { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] pub struct Attributes { pub doc_strings: Vec<DocFragment>, - pub other_attrs: Vec<ast::Attribute>, + pub other_attrs: Vec<hir::Attribute>, pub cfg: Option<Arc<Cfg>>, pub span: Option<syntax_pos::Span>, /// map from Rust paths to resolved defs and potential URL fragments @@ -771,7 +771,7 @@ pub struct Attributes { impl Attributes { /// Extracts the content from an attribute `#[doc(cfg(content))]`. - fn extract_cfg(mi: &ast::MetaItem) -> Option<&ast::MetaItem> { + fn extract_cfg(mi: &hir::MetaItem) -> Option<&hir::MetaItem> { use syntax::ast::NestedMetaItemKind::MetaItem; if let ast::MetaItemKind::List(ref nmis) = mi.node { @@ -796,7 +796,7 @@ impl Attributes { /// Reads a `MetaItem` from within an attribute, looks for whether it is a /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from /// its expansion. - fn extract_include(mi: &ast::MetaItem) + fn extract_include(mi: &hir::MetaItem) -> Option<(String, String)> { mi.meta_item_list().and_then(|list| { @@ -849,7 +849,7 @@ impl Attributes { } pub fn from_ast(diagnostic: &::errors::Handler, - attrs: &[ast::Attribute]) -> Attributes { + attrs: &[hir::Attribute]) -> Attributes { let mut doc_strings = vec![]; let mut sp = None; let mut cfg = Cfg::True; @@ -902,8 +902,9 @@ impl Attributes { for attr in attrs.lists("target_feature") { if attr.check_name("enable") { if let Some(feat) = attr.value_str() { - let meta = attr::mk_name_value_item_str(Ident::from_str("target_feature"), - dummy_spanned(feat)); + let meta: hir::MetaItem = + attr::mk_name_value_item_str(Ident::from_str("target_feature"), + dummy_spanned(feat)); if let Ok(feat_cfg) = Cfg::parse(&meta) { cfg &= feat_cfg; } @@ -1015,7 +1016,7 @@ impl AttributesExt for Attributes { } } -impl Clean<Attributes> for [ast::Attribute] { +impl Clean<Attributes> for [hir::Attribute] { fn clean(&self, cx: &DocContext) -> Attributes { Attributes::from_ast(cx.sess().diagnostic(), self) } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 4a6a4ee09ea1a..10fa8a647ff1b 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -25,7 +25,7 @@ use rustc::hir::def_id::CrateNum; pub struct Module { pub name: Option<Name>, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub where_outer: Span, pub where_inner: Span, pub extern_crates: Vec<ExternCrate>, @@ -101,7 +101,7 @@ pub struct Struct { pub struct_type: StructType, pub name: Name, pub generics: hir::Generics, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub fields: hir::HirVec<hir::StructField>, pub whence: Span, } @@ -114,7 +114,7 @@ pub struct Union { pub struct_type: StructType, pub name: Name, pub generics: hir::Generics, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub fields: hir::HirVec<hir::StructField>, pub whence: Span, } @@ -125,7 +125,7 @@ pub struct Enum { pub depr: Option<attr::Deprecation>, pub variants: hir::HirVec<Variant>, pub generics: hir::Generics, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub id: NodeId, pub whence: Span, pub name: Name, @@ -133,7 +133,7 @@ pub struct Enum { pub struct Variant { pub name: Name, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub def: hir::VariantData, pub stab: Option<attr::Stability>, pub depr: Option<attr::Deprecation>, @@ -142,7 +142,7 @@ pub struct Variant { pub struct Function { pub decl: hir::FnDecl, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub id: NodeId, pub name: Name, pub vis: hir::Visibility, @@ -159,7 +159,7 @@ pub struct Typedef { pub gen: hir::Generics, pub name: Name, pub id: ast::NodeId, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, pub vis: hir::Visibility, pub stab: Option<attr::Stability>, @@ -170,7 +170,7 @@ pub struct Existential { pub exist_ty: hir::ExistTy, pub name: Name, pub id: ast::NodeId, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, pub vis: hir::Visibility, pub stab: Option<attr::Stability>, @@ -183,7 +183,7 @@ pub struct Static { pub mutability: hir::Mutability, pub expr: hir::BodyId, pub name: Name, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub vis: hir::Visibility, pub stab: Option<attr::Stability>, pub depr: Option<attr::Deprecation>, @@ -195,7 +195,7 @@ pub struct Constant { pub type_: P<hir::Ty>, pub expr: hir::BodyId, pub name: Name, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub vis: hir::Visibility, pub stab: Option<attr::Stability>, pub depr: Option<attr::Deprecation>, @@ -210,7 +210,7 @@ pub struct Trait { pub items: hir::HirVec<hir::TraitItem>, pub generics: hir::Generics, pub bounds: hir::HirVec<hir::GenericBound>, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub id: ast::NodeId, pub whence: Span, pub vis: hir::Visibility, @@ -227,7 +227,7 @@ pub struct Impl { pub trait_: Option<hir::TraitRef>, pub for_: P<hir::Ty>, pub items: hir::HirVec<hir::ImplItem>, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, pub vis: hir::Visibility, pub stab: Option<attr::Stability>, @@ -240,7 +240,7 @@ pub struct Impl { pub struct Macro { pub name: Name, pub def_id: hir::def_id::DefId, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, pub matchers: hir::HirVec<Span>, pub stab: Option<attr::Stability>, @@ -253,7 +253,7 @@ pub struct ExternCrate { pub cnum: CrateNum, pub path: Option<String>, pub vis: hir::Visibility, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, } @@ -261,7 +261,7 @@ pub struct Import { pub name: Name, pub id: NodeId, pub vis: hir::Visibility, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub path: hir::Path, pub glob: bool, pub whence: Span, @@ -272,7 +272,7 @@ pub struct ProcMacro { pub id: NodeId, pub kind: MacroKind, pub helpers: Vec<Name>, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub whence: Span, pub stab: Option<attr::Stability>, pub depr: Option<attr::Deprecation>, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b46efb20d8f6b..ff77d1bccd57e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -54,7 +54,6 @@ use std::rc::Rc; use errors; use serialize::json::{ToJson, Json, as_json}; -use syntax::ast; use syntax::ext::base::MacroKind; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; @@ -3495,7 +3494,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Ok(()) } -fn render_attribute(attr: &ast::MetaItem) -> Option<String> { +fn render_attribute(attr: &hir::MetaItem) -> Option<String> { let name = attr.name(); if attr.is_word() { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d9bab91fd0c78..7e9f2216ef4c7 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -736,7 +736,7 @@ struct HirCollector<'a, 'hir: 'a> { impl<'a, 'hir> HirCollector<'a, 'hir> { fn visit_testable<F: FnOnce(&mut Self)>(&mut self, name: String, - attrs: &[ast::Attribute], + attrs: &[hir::Attribute], nested: F) { let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs); if let Some(ref cfg) = attrs.cfg { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5d221d3006f3e..c312d45501946 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -41,7 +41,7 @@ use doctree::*; pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { pub module: Module, - pub attrs: hir::HirVec<ast::Attribute>, + pub attrs: hir::HirVec<hir::Attribute>, pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, view_item_stack: FxHashSet<ast::NodeId>, inlining: bool, @@ -241,7 +241,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { } } - pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribute>, + pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<hir::Attribute>, vis: hir::Visibility, id: ast::NodeId, m: &hir::Mod, name: Option<ast::Name>) -> Module { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 227017a9073fe..523aac5e6e7d9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -410,15 +410,15 @@ pub struct Crate { } /// A spanned compile-time attribute list item. -pub type NestedMetaItem = Spanned<NestedMetaItemKind>; +pub type NestedMetaItem<Path = self::Path> = Spanned<NestedMetaItemKind<Path>>; /// Possible values inside of compile-time attribute lists. /// /// E.g. the '..' in `#[name(..)]`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum NestedMetaItemKind { +pub enum NestedMetaItemKind<Path = self::Path> { /// A full MetaItem, for recursive meta items. - MetaItem(MetaItem), + MetaItem(MetaItem<Path>), /// A literal. /// /// E.g. "foo", 64, true @@ -429,9 +429,9 @@ pub enum NestedMetaItemKind { /// /// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]` #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct MetaItem { +pub struct MetaItem<Path = self::Path> { pub ident: Path, - pub node: MetaItemKind, + pub node: MetaItemKind<Path>, pub span: Span, } @@ -439,7 +439,7 @@ pub struct MetaItem { /// /// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum MetaItemKind { +pub enum MetaItemKind<Path = self::Path> { /// Word meta item. /// /// E.g. `test` as in `#[test]` @@ -447,7 +447,7 @@ pub enum MetaItemKind { /// List meta item. /// /// E.g. `derive(..)` as in `#[derive(..)]` - List(Vec<NestedMetaItem>), + List(Vec<NestedMetaItem<Path>>), /// Name value meta item. /// /// E.g. `feature = "foo"` as in `#[feature = "foo"]` @@ -1985,7 +1985,7 @@ impl Idx for AttrId { /// Meta-data associated with an item /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Attribute { +pub struct Attribute<Path = self::Path> { pub id: AttrId, pub style: AttrStyle, pub path: Path, diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 1bbc1accc07d6..b47dabf440ac3 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -16,7 +16,7 @@ use feature_gate::{Features, GatedCfg}; use parse::ParseSess; use syntax_pos::{symbol::Symbol, Span}; -use super::{list_contains_name, mark_used, MetaItemKind}; +use super::{list_contains_name, mark_used, MetaItemKind, Path}; enum AttrError { MultipleItem(Name), @@ -80,8 +80,11 @@ pub enum UnwindAttr { } /// Determine what `#[unwind]` attribute is present in `attrs`, if any. -pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> { - let syntax_error = |attr: &Attribute| { +pub fn find_unwind_attr( + diagnostic: Option<&Handler>, + attrs: &[Attribute<impl Path>], +) -> Option<UnwindAttr> { + let syntax_error = |attr: &Attribute<_>| { mark_used(attr); diagnostic.map(|d| { span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute"); @@ -90,7 +93,7 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op }; attrs.iter().fold(None, |ia, attr| { - if attr.path != "unwind" { + if !attr.check_name_no_mark_used("unwind") { return ia; } let meta = match attr.meta() { @@ -165,7 +168,7 @@ pub struct RustcDeprecation { /// Check if `attrs` contains an attribute like `#![feature(feature_name)]`. /// This will not perform any "sanity checks" on the form of the attributes. -pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { +pub fn contains_feature_attr(attrs: &[Attribute<impl Path>], feature_name: &str) -> bool { attrs.iter().any(|item| { item.check_name("feature") && item.meta_item_list().map(|list| { @@ -178,17 +181,16 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { } /// Find the first stability attribute. `None` if none exists. -pub fn find_stability(sess: &ParseSess, attrs: &[Attribute], +pub fn find_stability(sess: &ParseSess, attrs: &[Attribute<impl Path>], item_sp: Span) -> Option<Stability> { find_stability_generic(sess, attrs.iter(), item_sp) } -fn find_stability_generic<'a, I>(sess: &ParseSess, - attrs_iter: I, - item_sp: Span) - -> Option<Stability> - where I: Iterator<Item = &'a Attribute> -{ +fn find_stability_generic<'a>( + sess: &ParseSess, + attrs_iter: impl Iterator<Item = &'a Attribute<impl Path>>, + item_sp: Span, +) -> Option<Stability> { use self::StabilityLevel::*; let mut stab: Option<Stability> = None; @@ -204,7 +206,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, "unstable", "stable", "rustc_promotable", - ].iter().any(|&s| attr.path == s) { + ].iter().any(|&s| attr.check_name_no_mark_used(s)) { continue // not a stability level } @@ -212,13 +214,13 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = attr.meta(); - if attr.path == "rustc_promotable" { + if attr.check_name_no_mark_used("rustc_promotable") { promotable = true; } // attributes with data else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta { let meta = meta.as_ref().unwrap(); - let get = |meta: &MetaItem, item: &mut Option<Symbol>| { + let get = |meta: &MetaItem<_>, item: &mut Option<Symbol>| { if item.is_some() { handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); return false @@ -488,19 +490,23 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, stab } -pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> { +pub fn find_crate_name(attrs: &[Attribute<impl Path>]) -> Option<Symbol> { super::first_attr_value_str_by_name(attrs, "crate_name") } /// Tests if a cfg-pattern matches the cfg set -pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool { +pub fn cfg_matches( + cfg: &ast::MetaItem<impl Path>, + sess: &ParseSess, + features: Option<&Features>, +) -> bool { eval_condition(cfg, sess, &mut |cfg| { if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) { gated_cfg.check_and_emit(sess, feats); } let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true }; - if cfg.ident.segments.len() != 1 { - return error(cfg.ident.span, "`cfg` predicate key must be an identifier"); + if cfg.ident.segments().len() != 1 { + return error(cfg.ident.span(), "`cfg` predicate key must be an identifier"); } match &cfg.node { MetaItemKind::List(..) => { @@ -526,10 +532,11 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. -pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) - -> bool - where F: FnMut(&ast::MetaItem) -> bool -{ +pub fn eval_condition<Path: self::Path>( + cfg: &ast::MetaItem<Path>, + sess: &ParseSess, + eval: &mut impl FnMut(&ast::MetaItem<Path>) -> bool, +) -> bool { match cfg.node { ast::MetaItemKind::List(ref mis) => { for mi in mis.iter() { @@ -583,22 +590,21 @@ pub struct Deprecation { } /// Find the deprecation attribute. `None` if none exists. -pub fn find_deprecation(sess: &ParseSess, attrs: &[Attribute], +pub fn find_deprecation(sess: &ParseSess, attrs: &[Attribute<impl Path>], item_sp: Span) -> Option<Deprecation> { find_deprecation_generic(sess, attrs.iter(), item_sp) } -fn find_deprecation_generic<'a, I>(sess: &ParseSess, - attrs_iter: I, - item_sp: Span) - -> Option<Deprecation> - where I: Iterator<Item = &'a Attribute> -{ +fn find_deprecation_generic<'a>( + sess: &ParseSess, + attrs_iter: impl Iterator<Item = &'a Attribute<impl Path>>, + item_sp: Span, +) -> Option<Deprecation> { let mut depr: Option<Deprecation> = None; let diagnostic = &sess.span_diagnostic; 'outer: for attr in attrs_iter { - if attr.path != "deprecated" { + if !attr.check_name_no_mark_used("deprecated") { continue } @@ -610,7 +616,7 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, } depr = if let Some(metas) = attr.meta_item_list() { - let get = |meta: &MetaItem, item: &mut Option<Symbol>| { + let get = |meta: &MetaItem<_>, item: &mut Option<Symbol>| { if item.is_some() { handle_errors(sess, meta.span, AttrError::MultipleItem(meta.name())); return false @@ -713,12 +719,12 @@ impl IntType { /// the same discriminant size that the corresponding C enum would or C /// structure layout, `packed` to remove padding, and `transparent` to elegate representation /// concerns to the only non-ZST field. -pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> { +pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute<impl Path>) -> Vec<ReprAttr> { use self::ReprAttr::*; let mut acc = Vec::new(); let diagnostic = &sess.span_diagnostic; - if attr.path == "repr" { + if attr.check_name_no_mark_used("repr") { if let Some(items) = attr.meta_item_list() { mark_used(attr); for item in items { diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 6487665947729..f30066e4f9a14 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -22,7 +22,7 @@ pub use self::ReprAttr::*; pub use self::StabilityLevel::*; use ast; -use ast::{AttrId, Attribute, AttrStyle, Name, Ident, Path, PathSegment}; +use ast::{AttrId, Attribute, AttrStyle, Name, Ident}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam}; use source_map::{BytePos, Spanned, respan, dummy_spanned}; @@ -37,29 +37,85 @@ use ThinVec; use tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; use GLOBALS; +use std::fmt; use std::iter; -pub fn mark_used(attr: &Attribute) { +pub trait Path: Clone + fmt::Debug + fmt::Display + 'static { + type Segment: PathSegment; + + fn from_ident(ident: Ident) -> Self { + Self::from_span_and_segments(ident.span, vec![Self::Segment::from_ident(ident)]) + } + fn from_span_and_segments(span: Span, segments: Vec<Self::Segment>) -> Self; + fn from_nt(nt: &token::Nonterminal) -> Result<Self, Option<MetaItem<Self>>>; + fn span(&self) -> Span; + fn segments(&self) -> &[Self::Segment]; +} + +pub trait PathSegment: 'static { + fn from_ident(ident: Ident) -> Self; + fn ident(&self) -> Ident; +} + +impl Path for ast::Path { + type Segment = ast::PathSegment; + + fn from_span_and_segments(span: Span, segments: Vec<Self::Segment>) -> Self { + Self { span, segments } + } + + fn from_nt(nt: &token::Nonterminal) -> Result<Self, Option<MetaItem<Self>>> { + match nt { + &token::Nonterminal::NtIdent(ident, _) => Ok(Self::from_ident(ident)), + token::Nonterminal::NtPath(path) => Ok(path.clone()), + token::Nonterminal::NtMeta(meta) => Err(Some(meta.clone())), + _ => Err(None), + } + } + + #[inline] + fn span(&self) -> Span { + self.span + } + + #[inline] + fn segments(&self) -> &[Self::Segment] { + &self.segments + } +} + +impl PathSegment for ast::PathSegment { + fn from_ident(ident: Ident) -> Self { + Self::from_ident(ident) + } + + #[inline] + fn ident(&self) -> Ident { + self.ident + } +} + +pub fn mark_used(attr: &Attribute<impl Path>) { debug!("Marking {:?} as used.", attr); GLOBALS.with(|globals| { globals.used_attrs.lock().insert(attr.id); }); } -pub fn is_used(attr: &Attribute) -> bool { +pub fn is_used(attr: &Attribute<impl Path>) -> bool { GLOBALS.with(|globals| { globals.used_attrs.lock().contains(attr.id) }) } -pub fn mark_known(attr: &Attribute) { +pub fn mark_known(attr: &Attribute<impl Path>) { debug!("Marking {:?} as known.", attr); GLOBALS.with(|globals| { globals.known_attrs.lock().insert(attr.id); }); } -pub fn is_known(attr: &Attribute) -> bool { +pub fn is_known(attr: &Attribute<impl Path>) -> bool { GLOBALS.with(|globals| { globals.known_attrs.lock().contains(attr.id) }) @@ -69,9 +125,9 @@ pub fn is_known_lint_tool(m_item: Ident) -> bool { ["clippy"].contains(&m_item.as_str().as_ref()) } -impl NestedMetaItem { +impl<Path: self::Path> NestedMetaItem<Path> { /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem. - pub fn meta_item(&self) -> Option<&MetaItem> { + pub fn meta_item(&self) -> Option<&MetaItem<Path>> { match self.node { NestedMetaItemKind::MetaItem(ref item) => Some(item), _ => None @@ -127,7 +183,7 @@ impl NestedMetaItem { } /// Returns a MetaItem if self is a MetaItem with Kind Word. - pub fn word(&self) -> Option<&MetaItem> { + pub fn word(&self) -> Option<&MetaItem<Path>> { self.meta_item().and_then(|meta_item| if meta_item.is_word() { Some(meta_item) } else { @@ -136,7 +192,7 @@ impl NestedMetaItem { } /// Gets a list of inner meta items from a list MetaItem type. - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { + pub fn meta_item_list(&self) -> Option<&[NestedMetaItem<Path>]> { self.meta_item().and_then(|meta_item| meta_item.meta_item_list()) } @@ -166,13 +222,18 @@ impl NestedMetaItem { } } -fn name_from_path(path: &Path) -> Name { - path.segments.last().expect("empty path in attribute").ident.name +fn name_from_path(path: &impl Path) -> Name { + path.segments().last().expect("empty path in attribute").ident().name } -impl Attribute { +impl<Path: self::Path> Attribute<Path> { + fn check_name_no_mark_used(&self, name: &str) -> bool { + self.path.segments().len() == 1 && + self.path.segments()[0].ident().name == name + } + pub fn check_name(&self, name: &str) -> bool { - let matches = self.path == name; + let matches = self.check_name_no_mark_used(name); if matches { mark_used(self); } @@ -189,7 +250,7 @@ impl Attribute { self.meta().and_then(|meta| meta.value_str()) } - pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> { + pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem<Path>>> { match self.meta() { Some(MetaItem { node: MetaItemKind::List(list), .. }) => Some(list), _ => None @@ -197,7 +258,7 @@ impl Attribute { } pub fn is_word(&self) -> bool { - self.path.segments.len() == 1 && self.tokens.is_empty() + self.path.segments().len() == 1 && self.tokens.is_empty() } pub fn span(&self) -> Span { @@ -214,7 +275,14 @@ impl Attribute { } } -impl MetaItem { +impl<Path: self::Path> MetaItem<Path> { + // FIXME(eddyb, petrochenkov) figure out whether + // the older `check_name` has been misused. + pub fn check_name_correct(&self, name: &str) -> bool { + self.ident.segments().len() == 1 && + self.ident.segments()[0].ident().name == name + } + pub fn name(&self) -> Name { name_from_path(&self.ident) } @@ -240,7 +308,7 @@ impl MetaItem { } } - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { + pub fn meta_item_list(&self) -> Option<&[NestedMetaItem<Path>]> { match self.node { MetaItemKind::List(ref l) => Some(&l[..]), _ => None @@ -269,17 +337,17 @@ impl MetaItem { } pub fn is_scoped(&self) -> Option<Ident> { - if self.ident.segments.len() > 1 { - Some(self.ident.segments[0].ident) + if self.ident.segments().len() > 1 { + Some(self.ident.segments()[0].ident()) } else { None } } } -impl Attribute { +impl<Path: self::Path> Attribute<Path> { /// Extract the MetaItem from inside this Attribute. - pub fn meta(&self) -> Option<MetaItem> { + pub fn meta(&self) -> Option<MetaItem<Path>> { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { ident: self.path.clone(), @@ -326,20 +394,10 @@ impl Attribute { }) } - pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { - Ok(MetaItem { - ident: self.path.clone(), - node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, - span: self.span, - }) - } - /// Convert self to a normal #[doc="foo"] comment, if it is a /// comment like `///` or `/** */`. (Returns self unchanged for /// non-sugared doc attributes.) - pub fn with_desugared_doc<T, F>(&self, f: F) -> T where - F: FnOnce(&Attribute) -> T, - { + pub fn with_desugared_doc<T>(&self, f: impl FnOnce(&Self) -> T) -> T { if self.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( @@ -358,26 +416,47 @@ impl Attribute { } } +impl Attribute { + pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { + Ok(MetaItem { + ident: self.path.clone(), + node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, + span: self.span, + }) + } +} + /* Constructors */ -pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem { +pub fn mk_name_value_item_str<Path: self::Path>( + ident: Ident, + value: Spanned<Symbol>, +) -> MetaItem<Path> { let value = respan(value.span, LitKind::Str(value.node, ast::StrStyle::Cooked)); mk_name_value_item(ident.span.to(value.span), ident, value) } -pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem { +pub fn mk_name_value_item<Path: self::Path>( + span: Span, + ident: Ident, + value: ast::Lit, +) -> MetaItem<Path> { MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } } -pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem { +pub fn mk_list_item<Path: self::Path>( + span: Span, + ident: Ident, + items: Vec<NestedMetaItem<Path>>, +) -> MetaItem<Path> { MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) } } -pub fn mk_word_item(ident: Ident) -> MetaItem { +pub fn mk_word_item<Path: self::Path>(ident: Ident) -> MetaItem<Path> { MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } } -pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { +pub fn mk_nested_word_item<Path: self::Path>(ident: Ident) -> NestedMetaItem<Path> { respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident))) } @@ -393,12 +472,20 @@ pub fn mk_attr_id() -> AttrId { } /// Returns an inner attribute with the given value. -pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute { +pub fn mk_attr_inner<Path: self::Path>( + span: Span, + id: AttrId, + item: MetaItem<Path>, +) -> Attribute<Path> { mk_spanned_attr_inner(span, id, item) } /// Returns an inner attribute with the given value and span. -pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute { +pub fn mk_spanned_attr_inner<Path: self::Path>( + sp: Span, + id: AttrId, + item: MetaItem<Path>, +) -> Attribute<Path> { Attribute { id, style: ast::AttrStyle::Inner, @@ -410,12 +497,20 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute } /// Returns an outer attribute with the given value. -pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute { +pub fn mk_attr_outer<Path: self::Path>( + span: Span, + id: AttrId, + item: MetaItem<Path>, +) -> Attribute<Path> { mk_spanned_attr_outer(span, id, item) } /// Returns an outer attribute with the given value and span. -pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute { +pub fn mk_spanned_attr_outer<Path: self::Path>( + sp: Span, + id: AttrId, + item: MetaItem<Path>, +) -> Attribute<Path> { Attribute { id, style: ast::AttrStyle::Outer, @@ -432,73 +527,80 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { Attribute { id, style, - path: Path::from_ident(Ident::from_str("doc").with_span_pos(span)), - tokens: MetaItemKind::NameValue(lit).tokens(span), + path: ast::Path::from_ident(Ident::from_str("doc").with_span_pos(span)), + tokens: MetaItemKind::NameValue::<ast::Path>(lit).tokens(span), is_sugared_doc: true, span, } } -pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool { +pub fn list_contains_name(items: &[NestedMetaItem<impl Path>], name: &str) -> bool { items.iter().any(|item| { item.check_name(name) }) } -pub fn contains_name(attrs: &[Attribute], name: &str) -> bool { +pub fn contains_name(attrs: &[Attribute<impl Path>], name: &str) -> bool { attrs.iter().any(|item| { item.check_name(name) }) } -pub fn find_by_name<'a>(attrs: &'a [Attribute], name: &str) -> Option<&'a Attribute> { +pub fn find_by_name<'a, Path: self::Path>( + attrs: &'a [Attribute<Path>], + name: &str, +) -> Option<&'a Attribute<Path>> { attrs.iter().find(|attr| attr.check_name(name)) } -pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: &'a str) - -> impl Iterator<Item = &'a Attribute> { +pub fn filter_by_name<'a, Path: self::Path>( + attrs: &'a [Attribute<Path>], + name: &'a str, +) -> impl Iterator<Item = &'a Attribute<Path>> { attrs.iter().filter(move |attr| attr.check_name(name)) } -pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<Symbol> { +pub fn first_attr_value_str_by_name(attrs: &[Attribute<impl Path>], name: &str) -> Option<Symbol> { attrs.iter() .find(|at| at.check_name(name)) .and_then(|at| at.value_str()) } -impl MetaItem { +impl<Path: self::Path> MetaItem<Path> { fn tokens(&self) -> TokenStream { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); - for (i, segment) in self.ident.segments.iter().enumerate() { + for (i, segment) in self.ident.segments().iter().enumerate() { let is_first = i == 0; if !is_first { let mod_sep_span = Span::new(last_pos, - segment.ident.span.lo(), - segment.ident.span.ctxt()); + segment.ident().span.lo(), + segment.ident().span.ctxt()); idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into()); } - idents.push(TokenTree::Token(segment.ident.span, - Token::from_ast_ident(segment.ident)).into()); - last_pos = segment.ident.span.hi(); + idents.push(TokenTree::Token(segment.ident().span, + Token::from_ast_ident(segment.ident())).into()); + last_pos = segment.ident().span.hi(); } idents.push(self.node.tokens(self.span)); TokenStream::concat(idents) } - fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem> + fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<Self> where I: Iterator<Item = TokenTree>, { // FIXME: Share code with `parse_path`. let ident = match tokens.next() { Some(TokenTree::Token(span, Token::Ident(ident, _))) => { if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() { - let mut segments = vec![PathSegment::from_ident(ident.with_span_pos(span))]; + let mut segments = vec![ + Path::Segment::from_ident(ident.with_span_pos(span)), + ]; tokens.next(); loop { if let Some(TokenTree::Token(span, Token::Ident(ident, _))) = tokens.next() { - segments.push(PathSegment::from_ident(ident.with_span_pos(span))); + segments.push(Path::Segment::from_ident(ident.with_span_pos(span))); } else { return None; } @@ -508,33 +610,33 @@ impl MetaItem { break; } } - let span = span.with_hi(segments.last().unwrap().ident.span.hi()); - Path { span, segments } + let span = span.with_hi(segments.last().unwrap().ident().span.hi()); + Path::from_span_and_segments(span, segments) } else { Path::from_ident(ident.with_span_pos(span)) } } - Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident), - token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), - token::Nonterminal::NtPath(ref path) => path.clone(), - _ => return None, - }, + Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => { + match Path::from_nt(&nt.0) { + Ok(path) => path, + Err(opt_meta) => return opt_meta, + } + } _ => return None, }; let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi()); let node = MetaItemKind::from_tokens(tokens)?; let hi = match node { MetaItemKind::NameValue(ref lit) => lit.span.hi(), - MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span.hi()), - _ => ident.span.hi(), + MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span().hi()), + _ => ident.span().hi(), }; - let span = ident.span.with_hi(hi); + let span = ident.span().with_hi(hi); Some(MetaItem { ident, node, span }) } } -impl MetaItemKind { +impl<Path: self::Path> MetaItemKind<Path> { pub fn tokens(&self, span: Span) -> TokenStream { match *self { MetaItemKind::Word => TokenStream::empty(), @@ -557,7 +659,7 @@ impl MetaItemKind { } } - fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItemKind> + fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<Self> where I: Iterator<Item = TokenTree>, { let delimited = match tokens.peek().cloned() { @@ -591,7 +693,7 @@ impl MetaItemKind { } } -impl NestedMetaItemKind { +impl<Path: self::Path> NestedMetaItemKind<Path> { fn span(&self) -> Span { match *self { NestedMetaItemKind::MetaItem(ref item) => item.span, @@ -606,7 +708,7 @@ impl NestedMetaItemKind { } } - fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItemKind> + fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<Self> where I: Iterator<Item = TokenTree>, { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { @@ -695,46 +797,73 @@ impl LitKind { } pub trait HasAttrs: Sized { - fn attrs(&self) -> &[ast::Attribute]; - fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self; + type Path: Path; + + fn attrs(&self) -> &[Attribute<Self::Path>]; + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self; } impl<T: HasAttrs> HasAttrs for Spanned<T> { - fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } - fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self { + type Path = T::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { self.node.attrs() } + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { respan(self.span, self.node.map_attrs(f)) } } -impl HasAttrs for Vec<Attribute> { - fn attrs(&self) -> &[Attribute] { +impl<Path: self::Path> HasAttrs for Vec<Attribute<Path>> { + type Path = Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { self } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { f(self) } } -impl HasAttrs for ThinVec<Attribute> { - fn attrs(&self) -> &[Attribute] { +impl<Path: self::Path> HasAttrs for ThinVec<Attribute<Path>> { + type Path = Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { self } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { f(self.into()).into() } } impl<T: HasAttrs + 'static> HasAttrs for P<T> { - fn attrs(&self) -> &[Attribute] { + type Path = T::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { (**self).attrs() } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { self.map(|t| t.map_attrs(f)) } } impl HasAttrs for StmtKind { - fn attrs(&self) -> &[Attribute] { + type Path = ast::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { match *self { StmtKind::Local(ref local) => local.attrs(), StmtKind::Item(..) => &[], @@ -746,7 +875,10 @@ impl HasAttrs for StmtKind { } } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { match self { StmtKind::Local(local) => StmtKind::Local(local.map_attrs(f)), StmtKind::Item(..) => self, @@ -760,18 +892,28 @@ impl HasAttrs for StmtKind { } impl HasAttrs for Stmt { - fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } - fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self { + type Path = ast::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { self.node.attrs() } + fn map_attrs( + self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { Stmt { id: self.id, node: self.node.map_attrs(f), span: self.span } } } impl HasAttrs for GenericParam { - fn attrs(&self) -> &[ast::Attribute] { + type Path = ast::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { &self.attrs } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(mut self, f: F) -> Self { + fn map_attrs( + mut self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { self.attrs = self.attrs.map_attrs(f); self } @@ -780,13 +922,16 @@ impl HasAttrs for GenericParam { macro_rules! derive_has_attrs { ($($ty:path),*) => { $( impl HasAttrs for $ty { - fn attrs(&self) -> &[Attribute] { + type Path = ast::Path; + + fn attrs(&self) -> &[Attribute<Self::Path>] { &self.attrs } - fn map_attrs<F>(mut self, f: F) -> Self - where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>, - { + fn map_attrs( + mut self, + f: impl FnOnce(Vec<Attribute<Self::Path>>) -> Vec<Attribute<Self::Path>>, + ) -> Self { self.attrs = self.attrs.map_attrs(f); self } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index d8fb20d425008..9196537ba2331 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -75,7 +75,7 @@ macro_rules! configure { } impl<'a> StripUnconfigured<'a> { - pub fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> { + pub fn configure<T: HasAttrs<Path = ast::Path>>(&mut self, node: T) -> Option<T> { let node = self.process_cfg_attrs(node); if self.in_cfg(node.attrs()) { Some(node) } else { None } } @@ -86,7 +86,7 @@ impl<'a> StripUnconfigured<'a> { /// Gives compiler warnigns if any `cfg_attr` does not contain any /// attributes and is in the original source code. Gives compiler errors if /// the syntax of any `cfg_attr` is incorrect. - pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: T) -> T { + pub fn process_cfg_attrs<T: HasAttrs<Path = ast::Path>>(&mut self, node: T) -> T { node.map_attrs(|attrs| { attrs.into_iter().flat_map(|attr| self.process_cfg_attr(attr)).collect() }) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bb927b62a181e..342ef01490509 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -46,6 +46,8 @@ pub enum Annotatable { } impl HasAttrs for Annotatable { + type Path = ast::Path; + fn attrs(&self) -> &[Attribute] { match *self { Annotatable::Item(ref item) => &item.attrs, @@ -57,7 +59,7 @@ impl HasAttrs for Annotatable { } } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { + fn map_attrs(self, f: impl FnOnce(Vec<Attribute>) -> Vec<Attribute>) -> Self { match self { Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)), Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)), diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 684cee3887463..f5310e8658c7c 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -46,7 +46,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec } pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path], item: T) -> T - where T: HasAttrs, + where T: HasAttrs<Path = ast::Path>, { let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned()); for (i, path) in traits.iter().enumerate() { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 68a96293891a0..915f7289e2490 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1129,7 +1129,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. fn classify_item<T>(&mut self, mut item: T) -> (Option<ast::Attribute>, Vec<Path>, T, /* after_derive */ bool) - where T: HasAttrs, + where T: HasAttrs<Path = ast::Path>, { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); @@ -1151,8 +1151,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough /// to the unused-attributes lint (making it an error on statements and expressions /// is a breaking change) - fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T) - -> (Option<ast::Attribute>, T, /* after_derive */ bool) { + fn classify_nonitem<T: HasAttrs<Path = ast::Path>>( + &mut self, + mut item: T, + ) -> (Option<ast::Attribute>, T, /* after_derive */ bool) { let (mut attr, mut after_derive) = (None, false); item = item.map_attrs(|mut attrs| { @@ -1169,7 +1171,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { (attr, item, after_derive) } - fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> { + fn configure<T: HasAttrs<Path = ast::Path>>(&mut self, node: T) -> Option<T> { self.cfg.configure(node) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index d0c4d1c7dce0a..f199d5ddd4e9e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1198,7 +1198,7 @@ pub struct GatedCfg { } impl GatedCfg { - pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> { + pub fn gate(cfg: &ast::MetaItem<impl attr::Path>) -> Option<GatedCfg> { let name = cfg.name().as_str(); GATED_CFGS.iter() .position(|info| info.0 == name) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 14ad4b5c6f815..3c7515d147a59 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -104,12 +104,14 @@ pub fn print_crate<'a>(cm: &'a SourceMap, // #![feature(prelude_import)] let pi_nested = attr::mk_nested_word_item(ast::Ident::from_str("prelude_import")); let list = attr::mk_list_item(DUMMY_SP, ast::Ident::from_str("feature"), vec![pi_nested]); - let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list); + let fake_attr: ast::Attribute = + attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list); s.print_attribute(&fake_attr)?; // #![no_std] let no_std_meta = attr::mk_word_item(ast::Ident::from_str("no_std")); - let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta); + let fake_attr: ast::Attribute = + attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta); s.print_attribute(&fake_attr)?; } @@ -401,15 +403,15 @@ pub fn block_to_string(blk: &ast::Block) -> String { }) } -pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String { +pub fn meta_list_item_to_string(li: &ast::NestedMetaItem<impl attr::Path>) -> String { to_string(|s| s.print_meta_list_item(li)) } -pub fn meta_item_to_string(mi: &ast::MetaItem) -> String { +pub fn meta_item_to_string(mi: &ast::MetaItem<impl attr::Path>) -> String { to_string(|s| s.print_meta_item(mi)) } -pub fn attribute_to_string(attr: &ast::Attribute) -> String { +pub fn attribute_to_string(attr: &ast::Attribute<impl attr::Path>) -> String { to_string(|s| s.print_attribute(attr)) } @@ -674,33 +676,33 @@ pub trait PrintState<'a> { } fn print_inner_attributes(&mut self, - attrs: &[ast::Attribute]) -> io::Result<()> { + attrs: &[ast::Attribute<impl attr::Path>]) -> io::Result<()> { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } fn print_inner_attributes_no_trailing_hardbreak(&mut self, - attrs: &[ast::Attribute]) + attrs: &[ast::Attribute<impl attr::Path>]) -> io::Result<()> { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) } fn print_outer_attributes(&mut self, - attrs: &[ast::Attribute]) -> io::Result<()> { + attrs: &[ast::Attribute<impl attr::Path>]) -> io::Result<()> { self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) } fn print_inner_attributes_inline(&mut self, - attrs: &[ast::Attribute]) -> io::Result<()> { + attrs: &[ast::Attribute<impl attr::Path>]) -> io::Result<()> { self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) } fn print_outer_attributes_inline(&mut self, - attrs: &[ast::Attribute]) -> io::Result<()> { + attrs: &[ast::Attribute<impl attr::Path>]) -> io::Result<()> { self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) } fn print_either_attributes(&mut self, - attrs: &[ast::Attribute], + attrs: &[ast::Attribute<impl attr::Path>], kind: ast::AttrStyle, is_inline: bool, trailing_hardbreak: bool) -> io::Result<()> { @@ -720,27 +722,29 @@ pub trait PrintState<'a> { Ok(()) } - fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> { - for (i, segment) in path.segments.iter().enumerate() { + fn print_attribute_path(&mut self, path: &impl attr::Path) -> io::Result<()> { + use attr::PathSegment; + + for (i, segment) in path.segments().iter().enumerate() { if i > 0 { self.writer().word("::")? } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() + if segment.ident().name != keywords::CrateRoot.name() && + segment.ident().name != keywords::DollarCrate.name() { - self.writer().word(segment.ident.as_str().get())?; - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; + self.writer().word(segment.ident().as_str().get())?; + } else if segment.ident().name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident().span.ctxt())?; } } Ok(()) } - fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> { + fn print_attribute(&mut self, attr: &ast::Attribute<impl attr::Path>) -> io::Result<()> { self.print_attribute_inline(attr, false) } - fn print_attribute_inline(&mut self, attr: &ast::Attribute, + fn print_attribute_inline(&mut self, attr: &ast::Attribute<impl attr::Path>, is_inline: bool) -> io::Result<()> { if !is_inline { self.hardbreak_if_not_bol()?; @@ -765,7 +769,10 @@ pub trait PrintState<'a> { } } - fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()> { + fn print_meta_list_item( + &mut self, + item: &ast::NestedMetaItem<impl attr::Path>, + ) -> io::Result<()> { match item.node { ast::NestedMetaItemKind::MetaItem(ref mi) => { self.print_meta_item(mi) @@ -776,7 +783,7 @@ pub trait PrintState<'a> { } } - fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> { + fn print_meta_item(&mut self, item: &ast::MetaItem<impl attr::Path>) -> io::Result<()> { self.ibox(INDENT_UNIT)?; match item.node { ast::MetaItemKind::Word => self.print_attribute_path(&item.ident)?,