Skip to content

Commit b93af01

Browse files
committedFeb 12, 2018
Allow Path for name of MetaItem
1 parent 77ced43 commit b93af01

File tree

10 files changed

+110
-77
lines changed

10 files changed

+110
-77
lines changed
 

‎src/librustc/ich/impls_syntax.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for [ast::Attribute] {
190190
}
191191
}
192192

193+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Path {
194+
fn hash_stable<W: StableHasherResult>(&self,
195+
hcx: &mut StableHashingContext<'gcx>,
196+
hasher: &mut StableHasher<W>) {
197+
self.segments.len().hash_stable(hcx, hasher);
198+
for segment in &self.segments {
199+
segment.identifier.name.hash_stable(hcx, hasher);
200+
}
201+
}
202+
}
203+
193204
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
194205
fn hash_stable<W: StableHasherResult>(&self,
195206
hcx: &mut StableHashingContext<'gcx>,
@@ -208,10 +219,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ast::Attribute {
208219
} = *self;
209220

210221
style.hash_stable(hcx, hasher);
211-
path.segments.len().hash_stable(hcx, hasher);
212-
for segment in &path.segments {
213-
segment.identifier.name.hash_stable(hcx, hasher);
214-
}
222+
path.hash_stable(hcx, hasher);
215223
for tt in tokens.trees() {
216224
tt.hash_stable(hcx, hasher);
217225
}

‎src/librustc_driver/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ impl RustcDefaultCalls {
10121012
let mut cfgs = Vec::new();
10131013
for &(name, ref value) in sess.parse_sess.config.iter() {
10141014
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
1015-
name,
1015+
name: ast::Path::from_ident(DUMMY_SP, name.to_ident()),
10161016
node: ast::MetaItemKind::Word,
10171017
span: DUMMY_SP,
10181018
});

‎src/librustc_resolve/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'a> base::Resolver for Resolver<'a> {
234234

235235
if name == "derive" {
236236
let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
237-
parser.parse_path_allowing_meta(PathStyle::Mod)
237+
parser.parse_path(PathStyle::Mod)
238238
});
239239

240240
let mut traits = match result {

‎src/libsyntax/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,10 @@ pub enum NestedMetaItemKind {
468468

469469
/// A spanned compile-time attribute item.
470470
///
471-
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
471+
/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`
472472
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
473473
pub struct MetaItem {
474-
pub name: Name,
474+
pub name: Path,
475475
pub node: MetaItemKind,
476476
pub span: Span,
477477
}

‎src/libsyntax/attr.rs

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use ast;
1818
use ast::{AttrId, Attribute, Name, Ident};
1919
use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
2020
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
21-
use codemap::{Spanned, respan, dummy_spanned};
21+
use codemap::{BytePos, Spanned, respan, dummy_spanned};
2222
use syntax_pos::{Span, DUMMY_SP};
2323
use errors::Handler;
2424
use feature_gate::{Features, GatedCfg};
@@ -205,6 +205,10 @@ impl NestedMetaItem {
205205
}
206206
}
207207

208+
fn name_from_path(path: &ast::Path) -> Name {
209+
path.segments.iter().next().unwrap().identifier.name
210+
}
211+
208212
impl Attribute {
209213
pub fn check_name(&self, name: &str) -> bool {
210214
let matches = self.path == name;
@@ -252,7 +256,7 @@ impl Attribute {
252256

253257
impl MetaItem {
254258
pub fn name(&self) -> Name {
255-
self.name
259+
name_from_path(&self.name)
256260
}
257261

258262
pub fn value_str(&self) -> Option<Symbol> {
@@ -301,10 +305,7 @@ impl Attribute {
301305
pub fn meta(&self) -> Option<MetaItem> {
302306
let mut tokens = self.tokens.trees().peekable();
303307
Some(MetaItem {
304-
name: match self.path.segments.len() {
305-
1 => self.path.segments[0].identifier.name,
306-
_ => return None,
307-
},
308+
name: self.path.clone(),
308309
node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
309310
if tokens.peek().is_some() {
310311
return None;
@@ -349,12 +350,8 @@ impl Attribute {
349350
}
350351

351352
pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
352-
if self.path.segments.len() > 1 {
353-
sess.span_diagnostic.span_err(self.path.span, "expected ident, found path");
354-
}
355-
356353
Ok(MetaItem {
357-
name: self.path.segments.last().unwrap().identifier.name,
354+
name: self.path.clone(),
358355
node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
359356
span: self.span,
360357
})
@@ -407,16 +404,26 @@ pub fn mk_word_item(name: Name) -> MetaItem {
407404
mk_spanned_word_item(DUMMY_SP, name)
408405
}
409406

407+
macro_rules! mk_spanned_meta_item {
408+
($sp:ident, $name:ident, $node:expr) => {
409+
MetaItem {
410+
span: $sp,
411+
name: ast::Path::from_ident($sp, ast::Ident::with_empty_ctxt($name)),
412+
node: $node,
413+
}
414+
}
415+
}
416+
410417
pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem {
411-
MetaItem { span: sp, name: name, node: MetaItemKind::NameValue(value) }
418+
mk_spanned_meta_item!(sp, name, MetaItemKind::NameValue(value))
412419
}
413420

414421
pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
415-
MetaItem { span: sp, name: name, node: MetaItemKind::List(items) }
422+
mk_spanned_meta_item!(sp, name, MetaItemKind::List(items))
416423
}
417424

418425
pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem {
419-
MetaItem { span: sp, name: name, node: MetaItemKind::Word }
426+
mk_spanned_meta_item!(sp, name, MetaItemKind::Word)
420427
}
421428

422429
pub fn mk_attr_id() -> AttrId {
@@ -440,7 +447,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
440447
Attribute {
441448
id,
442449
style: ast::AttrStyle::Inner,
443-
path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
450+
path: item.name,
444451
tokens: item.node.tokens(item.span),
445452
is_sugared_doc: false,
446453
span: sp,
@@ -458,7 +465,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
458465
Attribute {
459466
id,
460467
style: ast::AttrStyle::Outer,
461-
path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
468+
path: item.name,
462469
tokens: item.node.tokens(item.span),
463470
is_sugared_doc: false,
464471
span: sp,
@@ -600,7 +607,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
600607

601608
// The unwraps below may look dangerous, but we've already asserted
602609
// that they won't fail with the loop above.
603-
match &*cfg.name.as_str() {
610+
match &*cfg.name().as_str() {
604611
"any" => mis.iter().any(|mi| {
605612
eval_condition(mi.meta_item().unwrap(), sess, eval)
606613
}),
@@ -731,7 +738,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
731738
}
732739
}
733740

734-
match &*meta.name.as_str() {
741+
match &*meta.name().as_str() {
735742
"rustc_deprecated" => {
736743
if rustc_depr.is_some() {
737744
span_err!(diagnostic, item_sp, E0540,
@@ -1106,18 +1113,52 @@ impl IntType {
11061113

11071114
impl MetaItem {
11081115
fn tokens(&self) -> TokenStream {
1109-
let ident = TokenTree::Token(self.span, Token::Ident(Ident::with_empty_ctxt(self.name)));
1110-
TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)])
1116+
let mut idents = vec![];
1117+
let mut last_pos = BytePos(0 as u32);
1118+
for (i, segment) in self.name.segments.iter().enumerate() {
1119+
let is_first = i == 0;
1120+
if !is_first {
1121+
let mod_sep_span = Span::new(last_pos, segment.span.lo(), segment.span.ctxt());
1122+
idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into());
1123+
}
1124+
idents.push(TokenTree::Token(segment.span, Token::Ident(segment.identifier)).into());
1125+
last_pos = segment.span.hi();
1126+
}
1127+
idents.push(self.node.tokens(self.span));
1128+
TokenStream::concat(idents)
11111129
}
11121130

11131131
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
11141132
where I: Iterator<Item = TokenTree>,
11151133
{
1116-
let (span, name) = match tokens.next() {
1117-
Some(TokenTree::Token(span, Token::Ident(ident))) => (span, ident.name),
1134+
let name = match tokens.next() {
1135+
Some(TokenTree::Token(span, Token::Ident(ident))) => {
1136+
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
1137+
tokens.next();
1138+
let mut segments = vec![];
1139+
loop {
1140+
if let Some(TokenTree::Token(span, Token::Ident(ident))) = tokens.next() {
1141+
segments.push(ast::PathSegment::from_ident(ident, span));
1142+
} else {
1143+
return None;
1144+
}
1145+
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
1146+
tokens.next();
1147+
} else {
1148+
break;
1149+
}
1150+
}
1151+
ast::Path { span, segments }
1152+
} else {
1153+
ast::Path::from_ident(span, ident)
1154+
}
1155+
}
11181156
Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
1119-
token::Nonterminal::NtIdent(ident) => (ident.span, ident.node.name),
1157+
token::Nonterminal::NtIdent(ident) => {
1158+
ast::Path::from_ident(ident.span, ident.node)
1159+
}
11201160
token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
1161+
token::Nonterminal::NtPath(ref path) => path.clone(),
11211162
_ => return None,
11221163
},
11231164
_ => return None,
@@ -1126,10 +1167,11 @@ impl MetaItem {
11261167
let node = MetaItemKind::from_tokens(tokens)?;
11271168
let hi = match node {
11281169
MetaItemKind::NameValue(ref lit) => lit.span.hi(),
1129-
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi()),
1130-
_ => span.hi(),
1170+
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(name.span.hi()),
1171+
_ => name.span.hi(),
11311172
};
1132-
Some(MetaItem { name, node, span: span.with_hi(hi) })
1173+
let span = name.span.with_hi(hi);
1174+
Some(MetaItem { name, node, span })
11331175
}
11341176
}
11351177

‎src/libsyntax/ext/derive.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
2626
return true;
2727
}
2828

29-
match attr.parse_list(cx.parse_sess,
30-
|parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
29+
match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) {
3130
Ok(ref traits) if traits.is_empty() => {
3231
cx.span_warn(attr.span, "empty trait list in `derive`");
3332
false

‎src/libsyntax/ext/expand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
689689
invoc.expansion_data.mark.set_expn_info(expn_info);
690690
let span = span.with_ctxt(self.cx.backtrace());
691691
let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
692-
name: keywords::Invalid.name(),
692+
name: Path::from_ident(DUMMY_SP, keywords::Invalid.ident()),
693693
span: DUMMY_SP,
694694
node: ast::MetaItemKind::Word,
695695
};

‎src/libsyntax/parse/attr.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ impl<'a> Parser<'a> {
158158
};
159159
Ok(if let Some(meta) = meta {
160160
self.bump();
161-
(ast::Path::from_ident(meta.span, ast::Ident::with_empty_ctxt(meta.name)),
162-
meta.node.tokens(meta.span))
161+
(meta.name, meta.node.tokens(meta.span))
163162
} else {
164163
(self.parse_path(PathStyle::Mod)?, self.parse_tokens())
165164
})
@@ -235,9 +234,10 @@ impl<'a> Parser<'a> {
235234
}
236235

237236
let lo = self.span;
238-
let ident = self.parse_ident()?;
237+
let name = self.parse_path(PathStyle::Mod)?;
239238
let node = self.parse_meta_item_kind()?;
240-
Ok(ast::MetaItem { name: ident.name, node: node, span: lo.to(self.prev_span) })
239+
let span = lo.to(self.prev_span);
240+
Ok(ast::MetaItem { name, node, span })
241241
}
242242

243243
pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {

‎src/libsyntax/parse/parser.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,26 +1988,6 @@ impl<'a> Parser<'a> {
19881988
Ok(ast::Path { segments, span: lo.to(self.prev_span) })
19891989
}
19901990

1991-
/// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
1992-
/// This is used when parsing derive macro paths in `#[derive]` attributes.
1993-
pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
1994-
let meta_ident = match self.token {
1995-
token::Interpolated(ref nt) => match nt.0 {
1996-
token::NtMeta(ref meta) => match meta.node {
1997-
ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
1998-
_ => None,
1999-
},
2000-
_ => None,
2001-
},
2002-
_ => None,
2003-
};
2004-
if let Some(ident) = meta_ident {
2005-
self.bump();
2006-
return Ok(ast::Path::from_ident(self.prev_span, ident));
2007-
}
2008-
self.parse_path(style)
2009-
}
2010-
20111991
fn parse_path_segments(&mut self,
20121992
segments: &mut Vec<PathSegment>,
20131993
style: PathStyle,

‎src/libsyntax/print/pprust.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,22 @@ pub trait PrintState<'a> {
708708
Ok(())
709709
}
710710

711+
fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> {
712+
for (i, segment) in path.segments.iter().enumerate() {
713+
if i > 0 {
714+
self.writer().word("::")?
715+
}
716+
if segment.identifier.name != keywords::CrateRoot.name() &&
717+
segment.identifier.name != keywords::DollarCrate.name()
718+
{
719+
self.writer().word(&segment.identifier.name.as_str())?;
720+
} else if segment.identifier.name == keywords::DollarCrate.name() {
721+
self.print_dollar_crate(segment.identifier.ctxt)?;
722+
}
723+
}
724+
Ok(())
725+
}
726+
711727
fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
712728
self.print_attribute_inline(attr, false)
713729
}
@@ -729,17 +745,7 @@ pub trait PrintState<'a> {
729745
if let Some(mi) = attr.meta() {
730746
self.print_meta_item(&mi)?
731747
} else {
732-
for (i, segment) in attr.path.segments.iter().enumerate() {
733-
if i > 0 {
734-
self.writer().word("::")?
735-
}
736-
if segment.identifier.name != keywords::CrateRoot.name() &&
737-
segment.identifier.name != keywords::DollarCrate.name() {
738-
self.writer().word(&segment.identifier.name.as_str())?;
739-
} else if segment.identifier.name == keywords::DollarCrate.name() {
740-
self.print_dollar_crate(segment.identifier.ctxt)?;
741-
}
742-
}
748+
self.print_attribute_path(&attr.path)?;
743749
self.writer().space()?;
744750
self.print_tts(attr.tokens.clone())?;
745751
}
@@ -761,16 +767,14 @@ pub trait PrintState<'a> {
761767
fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
762768
self.ibox(INDENT_UNIT)?;
763769
match item.node {
764-
ast::MetaItemKind::Word => {
765-
self.writer().word(&item.name.as_str())?;
766-
}
770+
ast::MetaItemKind::Word => self.print_attribute_path(&item.name)?,
767771
ast::MetaItemKind::NameValue(ref value) => {
768-
self.word_space(&item.name.as_str())?;
772+
self.print_attribute_path(&item.name)?;
769773
self.word_space("=")?;
770774
self.print_literal(value)?;
771775
}
772776
ast::MetaItemKind::List(ref items) => {
773-
self.writer().word(&item.name.as_str())?;
777+
self.print_attribute_path(&item.name)?;
774778
self.popen()?;
775779
self.commasep(Consistent,
776780
&items[..],

0 commit comments

Comments
 (0)