Skip to content

Commit 759bd01

Browse files
topecongiroflip1995
authored andcommitted
Allow Path for name of MetaItem
1 parent e27d20a commit 759bd01

File tree

9 files changed

+141
-70
lines changed

9 files changed

+141
-70
lines changed

src/librustc/ich/impls_syntax.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,17 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
211211
}
212212
}
213213

214+
impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
215+
fn hash_stable<W: StableHasherResult>(&self,
216+
hcx: &mut StableHashingContext<'a>,
217+
hasher: &mut StableHasher<W>) {
218+
self.segments.len().hash_stable(hcx, hasher);
219+
for segment in &self.segments {
220+
segment.identifier.name.hash_stable(hcx, hasher);
221+
}
222+
}
223+
}
224+
214225
impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
215226
fn hash_stable<W: StableHasherResult>(&self,
216227
hcx: &mut StableHashingContext<'a>,
@@ -229,10 +240,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
229240
} = *self;
230241

231242
style.hash_stable(hcx, hasher);
232-
path.segments.len().hash_stable(hcx, hasher);
233-
for segment in &path.segments {
234-
segment.ident.name.hash_stable(hcx, hasher);
235-
}
243+
path.hash_stable(hcx, hasher);
236244
for tt in tokens.trees() {
237245
tt.hash_stable(hcx, hasher);
238246
}

src/librustc_driver/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ impl RustcDefaultCalls {
10601060
let mut cfgs = Vec::new();
10611061
for &(name, ref value) in sess.parse_sess.config.iter() {
10621062
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
1063-
ident: ast::Ident::with_empty_ctxt(name),
1063+
name: ast::Path::from_ident(DUMMY_SP, name.to_ident()),
10641064
node: ast::MetaItemKind::Word,
10651065
span: DUMMY_SP,
10661066
});

src/librustc_resolve/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ impl<'a> base::Resolver for Resolver<'a> {
235235

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

241241
let mut traits = match result {

src/libsyntax/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -474,10 +474,10 @@ pub enum NestedMetaItemKind {
474474

475475
/// A spanned compile-time attribute item.
476476
///
477-
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
477+
/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`
478478
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
479479
pub struct MetaItem {
480-
pub ident: Ident,
480+
pub name: Path,
481481
pub node: MetaItemKind,
482482
pub span: Span,
483483
}

src/libsyntax/attr.rs

+99-40
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl NestedMetaItem {
137137
/// Returns the name of the meta item, e.g. `foo` in `#[foo]`,
138138
/// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
139139
pub fn name(&self) -> Option<Name> {
140-
self.meta_item().and_then(|meta_item| Some(meta_item.ident.name))
140+
self.meta_item().and_then(|meta_item| Some(meta_item.name()))
141141
}
142142

143143
/// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -154,7 +154,7 @@ impl NestedMetaItem {
154154
if meta_item_list.len() == 1 {
155155
let nested_item = &meta_item_list[0];
156156
if nested_item.is_literal() {
157-
Some((meta_item.ident.name, nested_item.literal().unwrap()))
157+
Some((meta_item.name(), nested_item.literal().unwrap()))
158158
} else {
159159
None
160160
}
@@ -204,6 +204,10 @@ impl NestedMetaItem {
204204
}
205205
}
206206

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

216220
pub fn name(&self) -> Option<Name> {
217221
match self.path.segments.len() {
218-
1 => Some(self.path.segments[0].ident.name),
222+
1 => Some(self.path.segments[0].identifier.name),
219223
_ => None,
220224
}
221225
}
@@ -250,6 +254,10 @@ impl Attribute {
250254
}
251255

252256
impl MetaItem {
257+
pub fn name(&self) -> Name {
258+
name_from_path(&self.name)
259+
}
260+
253261
pub fn value_str(&self) -> Option<Symbol> {
254262
match self.node {
255263
MetaItemKind::NameValue(ref v) => {
@@ -279,7 +287,7 @@ impl MetaItem {
279287
pub fn span(&self) -> Span { self.span }
280288

281289
pub fn check_name(&self, name: &str) -> bool {
282-
self.ident.name == name
290+
self.name() == name
283291
}
284292

285293
pub fn is_value_str(&self) -> bool {
@@ -296,10 +304,7 @@ impl Attribute {
296304
pub fn meta(&self) -> Option<MetaItem> {
297305
let mut tokens = self.tokens.trees().peekable();
298306
Some(MetaItem {
299-
ident: match self.path.segments.len() {
300-
1 => self.path.segments[0].ident,
301-
_ => return None,
302-
},
307+
name: self.path.clone(),
303308
node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
304309
if tokens.peek().is_some() {
305310
return None;
@@ -344,12 +349,8 @@ impl Attribute {
344349
}
345350

346351
pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
347-
if self.path.segments.len() > 1 {
348-
sess.span_diagnostic.span_err(self.path.span, "expected ident, found path");
349-
}
350-
351352
Ok(MetaItem {
352-
ident: self.path.segments.last().unwrap().ident,
353+
name: self.path.clone(),
353354
node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
354355
span: self.span,
355356
})
@@ -397,8 +398,31 @@ pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> Met
397398
pub fn mk_word_item(ident: Ident) -> MetaItem {
398399
MetaItem { ident, span: ident.span, node: MetaItemKind::Word }
399400
}
400-
pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
401-
respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident)))
401+
402+
pub fn mk_word_item(name: Name) -> MetaItem {
403+
mk_spanned_word_item(DUMMY_SP, name)
404+
}
405+
406+
macro_rules! mk_spanned_meta_item {
407+
($sp:ident, $name:ident, $node:expr) => {
408+
MetaItem {
409+
span: $sp,
410+
name: ast::Path::from_ident($sp, ast::Ident::with_empty_ctxt($name)),
411+
node: $node,
412+
}
413+
}
414+
}
415+
416+
pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem {
417+
mk_spanned_meta_item!(sp, name, MetaItemKind::NameValue(value))
418+
}
419+
420+
pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
421+
mk_spanned_meta_item!(sp, name, MetaItemKind::List(items))
422+
}
423+
424+
pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem {
425+
mk_spanned_meta_item!(sp, name, MetaItemKind::Word)
402426
}
403427

404428
pub fn mk_attr_id() -> AttrId {
@@ -422,7 +446,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
422446
Attribute {
423447
id,
424448
style: ast::AttrStyle::Inner,
425-
path: ast::Path::from_ident(item.ident),
449+
path: item.name,
426450
tokens: item.node.tokens(item.span),
427451
is_sugared_doc: false,
428452
span: sp,
@@ -440,7 +464,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
440464
Attribute {
441465
id,
442466
style: ast::AttrStyle::Outer,
443-
path: ast::Path::from_ident(item.ident),
467+
path: item.name,
444468
tokens: item.node.tokens(item.span),
445469
is_sugared_doc: false,
446470
span: sp,
@@ -489,7 +513,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
489513
item.check_name("feature") &&
490514
item.meta_item_list().map(|list| {
491515
list.iter().any(|mi| {
492-
mi.word().map(|w| w.ident.name == feature_name)
516+
mi.word().map(|w| w.name() == feature_name)
493517
.unwrap_or(false)
494518
})
495519
}).unwrap_or(false)
@@ -562,7 +586,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
562586
if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
563587
gated_cfg.check_and_emit(sess, feats);
564588
}
565-
sess.config.contains(&(cfg.ident.name, cfg.value_str()))
589+
sess.config.contains(&(cfg.name(), cfg.value_str()))
566590
})
567591
}
568592

@@ -583,7 +607,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
583607

584608
// The unwraps below may look dangerous, but we've already asserted
585609
// that they won't fail with the loop above.
586-
match &*cfg.ident.name.as_str() {
610+
match &*cfg.name().as_str() {
587611
"any" => mis.iter().any(|mi| {
588612
eval_condition(mi.meta_item().unwrap(), sess, eval)
589613
}),
@@ -676,7 +700,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
676700
let meta = meta.as_ref().unwrap();
677701
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
678702
if item.is_some() {
679-
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
703+
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
680704
return false
681705
}
682706
if let Some(v) = meta.value_str() {
@@ -695,14 +719,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
695719
)+
696720
for meta in metas {
697721
if let Some(mi) = meta.meta_item() {
698-
match &*mi.ident.name.as_str() {
722+
match &*mi.name().as_str() {
699723
$(
700724
stringify!($name)
701725
=> if !get(mi, &mut $name) { continue 'outer },
702726
)+
703727
_ => {
704728
handle_errors(diagnostic, mi.span,
705-
AttrError::UnknownMetaItem(mi.ident.name));
729+
AttrError::UnknownMetaItem(mi.name()));
706730
continue 'outer
707731
}
708732
}
@@ -714,7 +738,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
714738
}
715739
}
716740

717-
match &*meta.ident.name.as_str() {
741+
match &*meta.name().as_str() {
718742
"rustc_deprecated" => {
719743
if rustc_depr.is_some() {
720744
span_err!(diagnostic, item_sp, E0540,
@@ -769,13 +793,13 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
769793
let mut issue = None;
770794
for meta in metas {
771795
if let Some(mi) = meta.meta_item() {
772-
match &*mi.ident.name.as_str() {
796+
match &*mi.name().as_str() {
773797
"feature" => if !get(mi, &mut feature) { continue 'outer },
774798
"reason" => if !get(mi, &mut reason) { continue 'outer },
775799
"issue" => if !get(mi, &mut issue) { continue 'outer },
776800
_ => {
777801
handle_errors(diagnostic, meta.span,
778-
AttrError::UnknownMetaItem(mi.ident.name));
802+
AttrError::UnknownMetaItem(mi.name()));
779803
continue 'outer
780804
}
781805
}
@@ -825,12 +849,12 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
825849
let mut since = None;
826850
for meta in metas {
827851
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
828-
match &*mi.ident.name.as_str() {
852+
match &*mi.name().as_str() {
829853
"feature" => if !get(mi, &mut feature) { continue 'outer },
830854
"since" => if !get(mi, &mut since) { continue 'outer },
831855
_ => {
832856
handle_errors(diagnostic, meta.span,
833-
AttrError::UnknownMetaItem(mi.ident.name));
857+
AttrError::UnknownMetaItem(mi.name()));
834858
continue 'outer
835859
}
836860
}
@@ -917,7 +941,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
917941
depr = if let Some(metas) = attr.meta_item_list() {
918942
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
919943
if item.is_some() {
920-
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
944+
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
921945
return false
922946
}
923947
if let Some(v) = meta.value_str() {
@@ -933,12 +957,12 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
933957
let mut note = None;
934958
for meta in metas {
935959
if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
936-
match &*mi.ident.name.as_str() {
960+
match &*mi.name().as_str() {
937961
"since" => if !get(mi, &mut since) { continue 'outer },
938962
"note" => if !get(mi, &mut note) { continue 'outer },
939963
_ => {
940964
handle_errors(diagnostic, meta.span,
941-
AttrError::UnknownMetaItem(mi.ident.name));
965+
AttrError::UnknownMetaItem(mi.name()));
942966
continue 'outer
943967
}
944968
}
@@ -990,7 +1014,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
9901014

9911015
let mut recognised = false;
9921016
if let Some(mi) = item.word() {
993-
let word = &*mi.ident.name.as_str();
1017+
let word = &*mi.name().as_str();
9941018
let hint = match word {
9951019
"C" => Some(ReprC),
9961020
"packed" => Some(ReprPacked(1)),
@@ -1127,18 +1151,52 @@ impl IntType {
11271151

11281152
impl MetaItem {
11291153
fn tokens(&self) -> TokenStream {
1130-
let ident = TokenTree::Token(self.span, Token::from_ast_ident(self.ident));
1131-
TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)])
1154+
let mut idents = vec![];
1155+
let mut last_pos = BytePos(0 as u32);
1156+
for (i, segment) in self.name.segments.iter().enumerate() {
1157+
let is_first = i == 0;
1158+
if !is_first {
1159+
let mod_sep_span = Span::new(last_pos, segment.span.lo(), segment.span.ctxt());
1160+
idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into());
1161+
}
1162+
idents.push(TokenTree::Token(segment.span, Token::Ident(segment.identifier)).into());
1163+
last_pos = segment.span.hi();
1164+
}
1165+
idents.push(self.node.tokens(self.span));
1166+
TokenStream::concat(idents)
11321167
}
11331168

11341169
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
11351170
where I: Iterator<Item = TokenTree>,
11361171
{
1137-
let (span, ident) = match tokens.next() {
1138-
Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident),
1172+
let name = match tokens.next() {
1173+
Some(TokenTree::Token(span, Token::Ident(ident))) => {
1174+
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
1175+
tokens.next();
1176+
let mut segments = vec![];
1177+
loop {
1178+
if let Some(TokenTree::Token(span, Token::Ident(ident))) = tokens.next() {
1179+
segments.push(ast::PathSegment::from_ident(ident, span));
1180+
} else {
1181+
return None;
1182+
}
1183+
if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() {
1184+
tokens.next();
1185+
} else {
1186+
break;
1187+
}
1188+
}
1189+
ast::Path { span, segments }
1190+
} else {
1191+
ast::Path::from_ident(span, ident)
1192+
}
1193+
}
11391194
Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
1140-
token::Nonterminal::NtIdent(ident, _) => (ident.span, ident),
1195+
token::Nonterminal::NtIdent(ident) => {
1196+
ast::Path::from_ident(ident.span, ident.node)
1197+
}
11411198
token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
1199+
token::Nonterminal::NtPath(ref path) => path.clone(),
11421200
_ => return None,
11431201
},
11441202
_ => return None,
@@ -1147,10 +1205,11 @@ impl MetaItem {
11471205
let node = MetaItemKind::from_tokens(tokens)?;
11481206
let hi = match node {
11491207
MetaItemKind::NameValue(ref lit) => lit.span.hi(),
1150-
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi()),
1151-
_ => span.hi(),
1208+
MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(name.span.hi()),
1209+
_ => name.span.hi(),
11521210
};
1153-
Some(MetaItem { ident, node, span: span.with_hi(hi) })
1211+
let span = name.span.with_hi(hi);
1212+
Some(MetaItem { name, node, span })
11541213
}
11551214
}
11561215

0 commit comments

Comments
 (0)