Skip to content

Commit 9c15de4

Browse files
committed
Auto merge of #40346 - jseyfried:path_and_tokenstream_attr, r=nrc
`TokenStream`-based attributes, paths in attribute and derive macro invocations This PR - refactors `Attribute` to use `Path` and `TokenStream` instead of `MetaItem`. - supports macro invocation paths for attribute procedural macros. - e.g. `#[::foo::attr_macro] struct S;`, `#[cfg_attr(all(), foo::attr_macro)] struct S;` - supports macro invocation paths for derive procedural macros. - e.g. `#[derive(foo::Bar, super::Baz)] struct S;` - supports arbitrary tokens as arguments to attribute procedural macros. - e.g. `#[foo::attr_macro arbitrary + tokens] struct S;` - supports using arbitrary tokens in "inert attributes" with derive procedural macros. - e.g. `#[derive(Foo)] struct S(#[inert arbitrary + tokens] i32);` where `#[proc_macro_derive(Foo, attributes(inert))]` r? @nrc
2 parents bfc49b1 + 85e02bd commit 9c15de4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+883
-539
lines changed

Diff for: src/librustc/hir/check_attr.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,12 @@ impl<'a> CheckAttrVisitor<'a> {
120120
}
121121

122122
fn check_attribute(&self, attr: &ast::Attribute, target: Target) {
123-
let name: &str = &attr.name().as_str();
124-
match name {
125-
"inline" => self.check_inline(attr, target),
126-
"repr" => self.check_repr(attr, target),
127-
_ => (),
123+
if let Some(name) = attr.name() {
124+
match &*name.as_str() {
125+
"inline" => self.check_inline(attr, target),
126+
"repr" => self.check_repr(attr, target),
127+
_ => (),
128+
}
128129
}
129130
}
130131
}

Diff for: src/librustc/hir/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,7 @@ impl<'a> LoweringContext<'a> {
12961296
let attrs = self.lower_attrs(&i.attrs);
12971297
let mut vis = self.lower_visibility(&i.vis);
12981298
if let ItemKind::MacroDef(ref tts) = i.node {
1299-
if i.attrs.iter().any(|attr| attr.name() == "macro_export") {
1299+
if i.attrs.iter().any(|attr| attr.path == "macro_export") {
13001300
self.exported_macros.push(hir::MacroDef {
13011301
name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
13021302
});

Diff for: src/librustc/lint/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -408,14 +408,14 @@ pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec<Result<(ast::Name, Level, S
408408
pub fn gather_attr(attr: &ast::Attribute) -> Vec<Result<(ast::Name, Level, Span), Span>> {
409409
let mut out = vec![];
410410

411-
let level = match Level::from_str(&attr.name().as_str()) {
411+
let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) {
412412
None => return out,
413413
Some(lvl) => lvl,
414414
};
415415

416+
let meta = unwrap_or!(attr.meta(), return out);
416417
attr::mark_used(attr);
417418

418-
let meta = &attr.value;
419419
let metas = if let Some(metas) = meta.meta_item_list() {
420420
metas
421421
} else {

Diff for: src/librustc/middle/stability.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
197197
} else {
198198
// Emit errors for non-staged-api crates.
199199
for attr in attrs {
200-
let tag = attr.name();
200+
let tag = unwrap_or!(attr.name(), continue);
201201
if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
202202
attr::mark_used(attr);
203203
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
@@ -402,7 +402,7 @@ impl<'a, 'tcx> Index<'tcx> {
402402

403403
let mut is_staged_api = false;
404404
for attr in &krate.attrs {
405-
if attr.name() == "stable" || attr.name() == "unstable" {
405+
if attr.path == "stable" || attr.path == "unstable" {
406406
is_staged_api = true;
407407
break
408408
}

Diff for: src/librustc/traits/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
274274
.filter(|a| a.check_name("rustc_on_unimplemented"))
275275
.next()
276276
{
277-
let err_sp = item.meta().span.substitute_dummy(span);
277+
let err_sp = item.span.substitute_dummy(span);
278278
let trait_str = self.tcx.item_path_str(trait_ref.def_id);
279279
if let Some(istring) = item.value_str() {
280280
let istring = &*istring.as_str();

Diff for: src/librustc_incremental/calculate_svh/svh_visitor.rs

+14-41
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,15 @@ use syntax::abi::Abi;
1818
use syntax::ast::{self, Name, NodeId};
1919
use syntax::attr;
2020
use syntax::parse::token;
21-
use syntax::symbol::{Symbol, InternedString};
21+
use syntax::symbol::InternedString;
2222
use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
2323
use syntax::tokenstream;
2424
use rustc::hir;
2525
use rustc::hir::*;
2626
use rustc::hir::def::Def;
2727
use rustc::hir::def_id::DefId;
28-
use rustc::hir::intravisit as visit;
28+
use rustc::hir::intravisit::{self as visit, Visitor};
2929
use rustc::ty::TyCtxt;
30-
use rustc_data_structures::fnv;
3130
use std::hash::{Hash, Hasher};
3231

3332
use super::def_path_hash::DefPathHashes;
@@ -559,7 +558,7 @@ macro_rules! hash_span {
559558
});
560559
}
561560

562-
impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
561+
impl<'a, 'hash, 'tcx> Visitor<'tcx> for StrictVersionHashVisitor<'a, 'hash, 'tcx> {
563562
fn nested_visit_map<'this>(&'this mut self) -> visit::NestedVisitorMap<'this, 'tcx> {
564563
if self.hash_bodies {
565564
visit::NestedVisitorMap::OnlyBodies(&self.tcx.hir)
@@ -960,50 +959,24 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
960959
}
961960
}
962961

963-
fn hash_meta_item(&mut self, meta_item: &ast::MetaItem) {
964-
debug!("hash_meta_item: st={:?}", self.st);
965-
966-
// ignoring span information, it doesn't matter here
967-
self.hash_discriminant(&meta_item.node);
968-
meta_item.name.as_str().len().hash(self.st);
969-
meta_item.name.as_str().hash(self.st);
970-
971-
match meta_item.node {
972-
ast::MetaItemKind::Word => {}
973-
ast::MetaItemKind::NameValue(ref lit) => saw_lit(lit).hash(self.st),
974-
ast::MetaItemKind::List(ref items) => {
975-
// Sort subitems so the hash does not depend on their order
976-
let indices = self.indices_sorted_by(&items, |p| {
977-
(p.name().map(Symbol::as_str), fnv::hash(&p.literal().map(saw_lit)))
978-
});
979-
items.len().hash(self.st);
980-
for (index, &item_index) in indices.iter().enumerate() {
981-
index.hash(self.st);
982-
let nested_meta_item: &ast::NestedMetaItemKind = &items[item_index].node;
983-
self.hash_discriminant(nested_meta_item);
984-
match *nested_meta_item {
985-
ast::NestedMetaItemKind::MetaItem(ref meta_item) => {
986-
self.hash_meta_item(meta_item);
987-
}
988-
ast::NestedMetaItemKind::Literal(ref lit) => {
989-
saw_lit(lit).hash(self.st);
990-
}
991-
}
992-
}
993-
}
994-
}
995-
}
996-
997962
pub fn hash_attributes(&mut self, attributes: &[ast::Attribute]) {
998963
debug!("hash_attributes: st={:?}", self.st);
999964
let indices = self.indices_sorted_by(attributes, |attr| attr.name());
1000965

1001966
for i in indices {
1002967
let attr = &attributes[i];
1003-
if !attr.is_sugared_doc &&
1004-
!IGNORED_ATTRIBUTES.contains(&&*attr.value.name().as_str()) {
968+
match attr.name() {
969+
Some(name) if IGNORED_ATTRIBUTES.contains(&&*name.as_str()) => continue,
970+
_ => {}
971+
};
972+
if !attr.is_sugared_doc {
1005973
SawAttribute(attr.style).hash(self.st);
1006-
self.hash_meta_item(&attr.value);
974+
for segment in &attr.path.segments {
975+
SawIdent(segment.identifier.name.as_str()).hash(self.st);
976+
}
977+
for tt in attr.tokens.trees() {
978+
self.hash_token_tree(&tt);
979+
}
1007980
}
1008981
}
1009982
}

Diff for: src/librustc_incremental/persist/dirty_clean.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
104104

105105
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
106106
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
107-
for item in attr.meta_item_list().unwrap_or(&[]) {
107+
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
108108
if item.check_name(LABEL) {
109-
let value = expect_associated_value(self.tcx, item);
109+
let value = expect_associated_value(self.tcx, &item);
110110
match DepNode::from_label_string(&value.as_str(), def_id) {
111111
Ok(def_id) => return def_id,
112112
Err(()) => {
@@ -331,9 +331,9 @@ fn check_config(tcx: TyCtxt, attr: &Attribute) -> bool {
331331
debug!("check_config(attr={:?})", attr);
332332
let config = &tcx.sess.parse_sess.config;
333333
debug!("check_config: config={:?}", config);
334-
for item in attr.meta_item_list().unwrap_or(&[]) {
334+
for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
335335
if item.check_name(CFG) {
336-
let value = expect_associated_value(tcx, item);
336+
let value = expect_associated_value(tcx, &item);
337337
debug!("check_config: searching for cfg {:?}", value);
338338
return config.contains(&(value, None));
339339
}

Diff for: src/librustc_lint/builtin.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ impl MissingDoc {
312312
}
313313
}
314314

315-
let has_doc = attrs.iter().any(|a| a.is_value_str() && a.name() == "doc");
315+
let has_doc = attrs.iter().any(|a| a.is_value_str() && a.check_name("doc"));
316316
if !has_doc {
317317
cx.span_lint(MISSING_DOCS,
318318
sp,
@@ -635,7 +635,7 @@ impl LintPass for DeprecatedAttr {
635635

636636
impl EarlyLintPass for DeprecatedAttr {
637637
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
638-
let name = attr.name();
638+
let name = unwrap_or!(attr.name(), return);
639639
for &&(n, _, ref g) in &self.depr_attrs {
640640
if name == n {
641641
if let &AttributeGate::Gated(Stability::Deprecated(link),
@@ -1121,8 +1121,8 @@ impl LintPass for UnstableFeatures {
11211121

11221122
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
11231123
fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
1124-
if attr.meta().check_name("feature") {
1125-
if let Some(items) = attr.meta().meta_item_list() {
1124+
if attr.check_name("feature") {
1125+
if let Some(items) = attr.meta_item_list() {
11261126
for item in items {
11271127
ctx.span_lint(UNSTABLE_FEATURES, item.span(), "unstable feature");
11281128
}

Diff for: src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#![feature(slice_patterns)]
3939
#![feature(staged_api)]
4040

41+
#[macro_use]
4142
extern crate syntax;
4243
#[macro_use]
4344
extern crate rustc;

Diff for: src/librustc_lint/unused.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl LintPass for UnusedAttributes {
269269
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
270270
fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
271271
debug!("checking attribute: {:?}", attr);
272+
let name = unwrap_or!(attr.name(), return);
272273

273274
// Note that check_name() marks the attribute as used if it matches.
274275
for &(ref name, ty, _) in BUILTIN_ATTRIBUTES {
@@ -294,13 +295,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
294295
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
295296
// Is it a builtin attribute that must be used at the crate level?
296297
let known_crate = BUILTIN_ATTRIBUTES.iter()
297-
.find(|&&(name, ty, _)| attr.name() == name && ty == AttributeType::CrateLevel)
298+
.find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel)
298299
.is_some();
299300

300301
// Has a plugin registered this attribute as one which must be used at
301302
// the crate level?
302303
let plugin_crate = plugin_attributes.iter()
303-
.find(|&&(ref x, t)| attr.name() == &**x && AttributeType::CrateLevel == t)
304+
.find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t)
304305
.is_some();
305306
if known_crate || plugin_crate {
306307
let msg = match attr.style {

Diff for: src/librustc_metadata/creader.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -973,9 +973,11 @@ impl<'a> CrateLoader<'a> {
973973

974974
impl<'a> CrateLoader<'a> {
975975
pub fn preprocess(&mut self, krate: &ast::Crate) {
976-
for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
977-
if let Some(linkarg) = attr.value_str() {
978-
self.cstore.add_used_link_args(&linkarg.as_str());
976+
for attr in &krate.attrs {
977+
if attr.path == "link_args" {
978+
if let Some(linkarg) = attr.value_str() {
979+
self.cstore.add_used_link_args(&linkarg.as_str());
980+
}
979981
}
980982
}
981983
}

Diff for: src/librustc_metadata/cstore.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,12 @@ impl CrateMetadata {
269269
}
270270

271271
pub fn is_staged_api(&self) -> bool {
272-
self.get_item_attrs(CRATE_DEF_INDEX)
273-
.iter()
274-
.any(|attr| attr.name() == "stable" || attr.name() == "unstable")
272+
for attr in self.get_item_attrs(CRATE_DEF_INDEX) {
273+
if attr.path == "stable" || attr.path == "unstable" {
274+
return true;
275+
}
276+
}
277+
false
275278
}
276279

277280
pub fn is_allocator(&self) -> bool {

Diff for: src/librustc_passes/ast_validation.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
241241
ItemKind::Mod(_) => {
242242
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
243243
attr::first_attr_value_str_by_name(&item.attrs, "path");
244-
if let Some(attr) =
245-
item.attrs.iter().find(|attr| attr.name() == "warn_directory_ownership") {
244+
if item.attrs.iter().any(|attr| attr.check_name("warn_directory_ownership")) {
246245
let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
247246
let msg = "cannot declare a new module at this location";
248247
self.session.add_lint(lint, item.id, item.span, msg.to_string());
249-
attr::mark_used(attr);
250248
}
251249
}
252250
ItemKind::Union(ref vdata, _) => {

Diff for: src/librustc_resolve/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,7 @@ pub struct Resolver<'a> {
11651165

11661166
privacy_errors: Vec<PrivacyError<'a>>,
11671167
ambiguity_errors: Vec<AmbiguityError<'a>>,
1168+
gated_errors: FxHashSet<Span>,
11681169
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
11691170

11701171
arenas: &'a ResolverArenas<'a>,
@@ -1355,6 +1356,7 @@ impl<'a> Resolver<'a> {
13551356

13561357
privacy_errors: Vec::new(),
13571358
ambiguity_errors: Vec::new(),
1359+
gated_errors: FxHashSet(),
13581360
disallowed_shadowing: Vec::new(),
13591361

13601362
arenas: arenas,
@@ -3359,8 +3361,9 @@ impl<'a> Resolver<'a> {
33593361
if self.proc_macro_enabled { return; }
33603362

33613363
for attr in attrs {
3362-
let maybe_binding = self.builtin_macros.get(&attr.name()).cloned().or_else(|| {
3363-
let ident = Ident::with_empty_ctxt(attr.name());
3364+
let name = unwrap_or!(attr.name(), continue);
3365+
let maybe_binding = self.builtin_macros.get(&name).cloned().or_else(|| {
3366+
let ident = Ident::with_empty_ctxt(name);
33643367
self.resolve_lexical_macro_path_segment(ident, MacroNS, None).ok()
33653368
});
33663369

0 commit comments

Comments
 (0)