Skip to content

Commit c84562e

Browse files
committed
Avoid modifying invocations in place for derive helper attributes
1 parent 467a7ab commit c84562e

File tree

3 files changed

+28
-59
lines changed

3 files changed

+28
-59
lines changed

src/librustc_resolve/macros.rs

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ use rustc::hir::map::{self, DefCollector};
2020
use rustc::{ty, lint};
2121
use rustc::middle::cstore::CrateStore;
2222
use syntax::ast::{self, Name, Ident};
23-
use syntax::attr::{self, HasAttrs};
23+
use syntax::attr;
2424
use syntax::errors::DiagnosticBuilder;
25-
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
25+
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
2626
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
27-
use syntax::ext::expand::{self, AstFragment, AstFragmentKind, Invocation, InvocationKind};
27+
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
2828
use syntax::ext::hygiene::{self, Mark};
29-
use syntax::ext::placeholders::placeholder;
3029
use syntax::ext::tt::macro_rules;
3130
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
3231
use syntax::fold::{self, Folder};
@@ -320,7 +319,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
320319
None
321320
}
322321

323-
fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
322+
fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
324323
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
325324
let def = match invoc.kind {
326325
InvocationKind::Attr { attr: None, .. } => return Ok(None),
@@ -330,17 +329,22 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
330329
self.report_proc_macro_stub(invoc.span());
331330
return Err(Determinacy::Determined);
332331
} else if let Def::NonMacroAttr(attr_kind) = def {
333-
let is_attr = if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
334-
if is_attr && attr_kind == NonMacroAttrKind::Tool {
335-
if !self.session.features_untracked().tool_attributes {
336-
feature_err(&self.session.parse_sess, "tool_attributes",
337-
invoc.span(), GateIssue::Language,
338-
"tool attributes are unstable").emit();
332+
let is_attr_invoc =
333+
if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
334+
match attr_kind {
335+
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper if is_attr_invoc => {
336+
if attr_kind == NonMacroAttrKind::Tool &&
337+
!self.session.features_untracked().tool_attributes {
338+
feature_err(&self.session.parse_sess, "tool_attributes",
339+
invoc.span(), GateIssue::Language,
340+
"tool attributes are unstable").emit();
341+
}
342+
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
343+
}
344+
_ => {
345+
self.report_non_macro_attr(invoc.path_span(), def);
346+
return Err(Determinacy::Determined);
339347
}
340-
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
341-
} else {
342-
self.report_non_macro_attr(invoc.path_span(), def);
343-
return Err(Determinacy::Determined);
344348
}
345349
}
346350
let def_id = def.def_id();
@@ -401,10 +405,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
401405
self.session.span_err(span, &format!("expected a macro, found {}", def.kind_name()));
402406
}
403407

404-
fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
408+
fn resolve_invoc_to_def(&mut self, invoc: &Invocation, scope: Mark, force: bool)
405409
-> Result<Def, Determinacy> {
406-
let (attr, traits, item) = match invoc.kind {
407-
InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
410+
let (attr, traits) = match invoc.kind {
411+
InvocationKind::Attr { ref attr, ref traits, .. } => (attr, traits),
408412
InvocationKind::Bang { ref mac, .. } => {
409413
return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force);
410414
}
@@ -413,7 +417,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
413417
}
414418
};
415419

416-
417420
let path = attr.as_ref().unwrap().path.clone();
418421
let mut determinacy = Determinacy::Determined;
419422
match self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force) {
@@ -434,11 +437,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
434437
// This loop here looks through all of the derive annotations in scope
435438
// and tries to resolve them. If they themselves successfully resolve
436439
// *and* the resolve mentions that this attribute's name is a registered
437-
// custom attribute then we flag this attribute as known and update
438-
// `invoc` above to point to the next invocation.
439-
//
440-
// By then returning `Undetermined` we should continue resolution to
441-
// resolve the next attribute.
440+
// custom attribute then we return that custom attribute as the resolution result.
442441
let attr_name = match path.segments.len() {
443442
1 => path.segments[0].ident.name,
444443
_ => return Err(determinacy),
@@ -447,20 +446,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
447446
match self.resolve_macro(scope, path, MacroKind::Derive, force) {
448447
Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs, _) = *ext {
449448
if inert_attrs.contains(&attr_name) {
450-
// FIXME(jseyfried) Avoid `mem::replace` here.
451-
let dummy_item = placeholder(AstFragmentKind::Items, ast::DUMMY_NODE_ID)
452-
.make_items().pop().unwrap();
453-
let dummy_item = Annotatable::Item(dummy_item);
454-
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
455-
let inert_attr = attr.take().unwrap();
456-
attr::mark_known(&inert_attr);
457-
if self.use_extern_macros {
458-
*attr = expand::find_attr_invoc(&mut attrs);
459-
}
460-
attrs.push(inert_attr);
461-
attrs
462-
});
463-
return Err(Determinacy::Undetermined)
449+
return Ok(Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper));
464450
}
465451
},
466452
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,

src/libsyntax/ext/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ pub trait Resolver {
726726
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool)
727727
-> Option<Attribute>;
728728

729-
fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
729+
fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
730730
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
731731
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
732732
-> Result<Lrc<SyntaxExtension>, Determinacy>;
@@ -754,7 +754,7 @@ impl Resolver for DummyResolver {
754754
fn resolve_imports(&mut self) {}
755755
fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
756756
-> Option<Attribute> { None }
757-
fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
757+
fn resolve_invoc(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool)
758758
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
759759
Err(Determinacy::Determined)
760760
}

src/libsyntax/ext/expand.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,6 @@ impl Invocation {
252252
InvocationKind::Derive { ref path, .. } => path.span,
253253
}
254254
}
255-
256-
pub fn attr_id(&self) -> Option<ast::AttrId> {
257-
match self.kind {
258-
InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
259-
_ => None,
260-
}
261-
}
262255
}
263256

264257
pub struct MacroExpander<'a, 'b:'a> {
@@ -338,7 +331,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
338331
let mut undetermined_invocations = Vec::new();
339332
let (mut progress, mut force) = (false, !self.monotonic);
340333
loop {
341-
let mut invoc = if let Some(invoc) = invocations.pop() {
334+
let invoc = if let Some(invoc) = invocations.pop() {
342335
invoc
343336
} else {
344337
self.resolve_imports();
@@ -350,20 +343,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
350343

351344
let scope =
352345
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
353-
let attr_id_before = invoc.attr_id();
354-
let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
346+
let ext = match self.cx.resolver.resolve_invoc(&invoc, scope, force) {
355347
Ok(ext) => Some(ext),
356348
Err(Determinacy::Determined) => None,
357349
Err(Determinacy::Undetermined) => {
358-
// Sometimes attributes which we thought were invocations
359-
// end up being custom attributes for custom derives. If
360-
// that's the case our `invoc` will have changed out from
361-
// under us. If this is the case we're making progress so we
362-
// want to flag it as such, and we test this by looking if
363-
// the `attr_id()` method has been changing over time.
364-
if invoc.attr_id() != attr_id_before {
365-
progress = true;
366-
}
367350
undetermined_invocations.push(invoc);
368351
continue
369352
}

0 commit comments

Comments
 (0)