Skip to content

Commit 421c5d1

Browse files
committed
Remove scope placeholders, remove method add_macro of ext::base::Resolver.
1 parent e80d1a8 commit 421c5d1

File tree

7 files changed

+91
-122
lines changed

7 files changed

+91
-122
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -697,9 +697,13 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
697697

698698
fn visit_item(&mut self, item: &'a Item) {
699699
let macro_use = match item.node {
700-
ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder
701-
ItemKind::Mac(..) => {
702-
return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
700+
ItemKind::Mac(ref mac) => {
701+
if mac.node.path.segments.is_empty() {
702+
self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
703+
} else {
704+
self.resolver.define_macro(item, &mut self.legacy_scope);
705+
}
706+
return
703707
}
704708
ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
705709
_ => false,

src/librustc_resolve/macros.rs

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use syntax::ast::{self, Name, Ident};
2323
use syntax::attr;
2424
use syntax::errors::DiagnosticBuilder;
2525
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
26-
use syntax::ext::base::{NormalTT, SyntaxExtension};
27-
use syntax::ext::expand::Expansion;
26+
use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
27+
use syntax::ext::expand::{Expansion, mark_tts};
2828
use syntax::ext::hygiene::Mark;
2929
use syntax::ext::tt::macro_rules;
3030
use syntax::feature_gate::{emit_feature_err, GateIssue};
@@ -139,34 +139,6 @@ impl<'a> base::Resolver for Resolver<'a> {
139139
invocation.expansion.set(visitor.legacy_scope);
140140
}
141141

142-
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) {
143-
if def.ident.name == "macro_rules" {
144-
self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
145-
}
146-
147-
let invocation = self.invocations[&scope];
148-
let binding = self.arenas.alloc_legacy_binding(LegacyBinding {
149-
parent: Cell::new(invocation.legacy_scope.get()),
150-
name: def.ident.name,
151-
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
152-
span: def.span,
153-
});
154-
invocation.legacy_scope.set(LegacyScope::Binding(binding));
155-
self.macro_names.insert(def.ident.name);
156-
157-
if attr::contains_name(&def.attrs, "macro_export") {
158-
def.id = self.next_node_id();
159-
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
160-
collector.visit_macro_def(&def)
161-
});
162-
self.macro_exports.push(Export {
163-
name: def.ident.name,
164-
def: Def::Macro(self.definitions.local_def_id(def.id)),
165-
});
166-
self.exported_macros.push(def);
167-
}
168-
}
169-
170142
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
171143
if let NormalTT(..) = *ext {
172144
self.macro_names.insert(ident.name);
@@ -444,4 +416,47 @@ impl<'a> Resolver<'a> {
444416
expansion.visit_with(def_collector)
445417
});
446418
}
419+
420+
pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
421+
let tts = match item.node {
422+
ast::ItemKind::Mac(ref mac) => &mac.node.tts,
423+
_ => unreachable!(),
424+
};
425+
426+
if item.ident.name == "macro_rules" {
427+
self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
428+
}
429+
430+
let mark = Mark::from_placeholder_id(item.id);
431+
let invocation = self.invocations[&mark];
432+
invocation.module.set(self.current_module);
433+
434+
let mut def = ast::MacroDef {
435+
ident: item.ident,
436+
attrs: item.attrs.clone(),
437+
id: ast::DUMMY_NODE_ID,
438+
span: item.span,
439+
body: mark_tts(tts, mark),
440+
};
441+
442+
*legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
443+
parent: Cell::new(*legacy_scope),
444+
name: def.ident.name,
445+
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
446+
span: def.span,
447+
}));
448+
self.macro_names.insert(def.ident.name);
449+
450+
if attr::contains_name(&def.attrs, "macro_export") {
451+
def.id = self.next_node_id();
452+
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
453+
collector.visit_macro_def(&def)
454+
});
455+
self.macro_exports.push(Export {
456+
name: def.ident.name,
457+
def: Def::Macro(self.definitions.local_def_id(def.id)),
458+
});
459+
self.exported_macros.push(def);
460+
}
461+
}
447462
}

src/libsyntax/ext/base.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,6 @@ pub trait Resolver {
520520
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
521521

522522
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
523-
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef);
524523
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
525524
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
526525

@@ -544,7 +543,6 @@ impl Resolver for DummyResolver {
544543
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
545544

546545
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
547-
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {}
548546
fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
549547
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
550548

src/libsyntax/ext/expand.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
392392
};
393393
let Mac_ { path, tts, .. } = mac.node;
394394

395-
// Detect use of feature-gated or invalid attributes on macro invoations
396-
// since they will not be detected after macro expansion.
397-
for attr in attrs.iter() {
398-
feature_gate::check_attribute(&attr, &self.cx.parse_sess,
399-
&self.cx.parse_sess.codemap(),
400-
&self.cx.ecfg.features.unwrap());
401-
}
402-
403395
let extname = path.segments.last().unwrap().identifier.name;
404396
let ident = ident.unwrap_or(keywords::Invalid.ident());
405397
let marked_tts = mark_tts(&tts, mark);
@@ -601,6 +593,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
601593
fn collect_bang(
602594
&mut self, mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span, kind: ExpansionKind,
603595
) -> Expansion {
596+
self.check_attributes(&attrs);
604597
self.collect(kind, InvocationKind::Bang { attrs: attrs, mac: mac, ident: None, span: span })
605598
}
606599

@@ -622,6 +615,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
622615
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
623616
self.cfg.configure(node)
624617
}
618+
619+
// Detect use of feature-gated or invalid attributes on macro invocations
620+
// since they will not be detected after macro expansion.
621+
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
622+
let codemap = &self.cx.parse_sess.codemap();
623+
let features = self.cx.ecfg.features.unwrap();
624+
for attr in attrs.iter() {
625+
feature_gate::check_attribute(&attr, &self.cx.parse_sess, codemap, features);
626+
}
627+
}
625628
}
626629

627630
// These are pretty nasty. Ideally, we would keep the tokens around, linked from
@@ -740,14 +743,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
740743

741744
match item.node {
742745
ast::ItemKind::Mac(..) => {
743-
if match item.node {
744-
ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(),
745-
_ => unreachable!(),
746-
} {
747-
return SmallVector::one(item);
748-
}
746+
self.check_attributes(&item.attrs);
747+
let is_macro_def = if let ItemKind::Mac(ref mac) = item.node {
748+
mac.node.path.segments[0].identifier.name == "macro_rules"
749+
} else {
750+
unreachable!()
751+
};
749752

750-
item.and_then(|item| match item.node {
753+
item.and_then(|mut item| match item.node {
754+
ItemKind::Mac(_) if is_macro_def => {
755+
item.id = ast::NodeId::from_u32(Mark::fresh().as_u32());
756+
SmallVector::one(P(item))
757+
}
751758
ItemKind::Mac(mac) => {
752759
self.collect(ExpansionKind::Items, InvocationKind::Bang {
753760
mac: mac,

src/libsyntax/ext/placeholders.rs

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use ast;
1212
use codemap::{DUMMY_SP, dummy_spanned};
1313
use ext::base::ExtCtxt;
1414
use ext::expand::{Expansion, ExpansionKind};
15+
use ext::hygiene::Mark;
1516
use fold::*;
1617
use ptr::P;
17-
use symbol::{Symbol, keywords};
18+
use symbol::keywords;
1819
use util::move_map::MoveMap;
1920
use util::small_vector::SmallVector;
2021

@@ -68,10 +69,6 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
6869
}
6970
}
7071

71-
pub fn macro_scope_placeholder() -> Expansion {
72-
placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
73-
}
74-
7572
pub struct PlaceholderExpander<'a, 'b: 'a> {
7673
expansions: HashMap<ast::NodeId, Expansion>,
7774
cx: &'a mut ExtCtxt<'b>,
@@ -100,11 +97,12 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
10097
impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
10198
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
10299
match item.node {
103-
// Scope placeholder
104-
ast::ItemKind::Mac(_) if item.id == ast::DUMMY_NODE_ID => SmallVector::one(item),
105-
ast::ItemKind::Mac(_) => self.remove(item.id).make_items(),
106-
_ => noop_fold_item(item, self),
100+
ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {}
101+
ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
102+
_ => {}
107103
}
104+
105+
noop_fold_item(item, self)
108106
}
109107

110108
fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
@@ -172,10 +170,10 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
172170
block.stmts = block.stmts.move_flat_map(|mut stmt| {
173171
remaining_stmts -= 1;
174172

175-
// Scope placeholder
173+
// `macro_rules!` macro definition
176174
if let ast::StmtKind::Item(ref item) = stmt.node {
177-
if let ast::ItemKind::Mac(..) = item.node {
178-
macros.push(item.ident.ctxt.data().outer_mark);
175+
if let ast::ItemKind::Mac(_) = item.node {
176+
macros.push(Mark::from_placeholder_id(item.id));
179177
return None;
180178
}
181179
}
@@ -208,33 +206,13 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
208206
fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
209207
let mut module = noop_fold_mod(module, self);
210208
module.items = module.items.move_flat_map(|item| match item.node {
211-
ast::ItemKind::Mac(_) => None, // remove scope placeholders from modules
209+
ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => None, // remove macro definitions
212210
_ => Some(item),
213211
});
214212
module
215213
}
216-
}
217214

218-
pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion {
219-
Expansion::Items(SmallVector::one(P(ast::Item {
220-
ident: def.ident,
221-
attrs: def.attrs.clone(),
222-
id: ast::DUMMY_NODE_ID,
223-
node: ast::ItemKind::Mac(ast::Mac {
224-
span: def.span,
225-
node: ast::Mac_ {
226-
path: ast::Path {
227-
span: DUMMY_SP,
228-
global: false,
229-
segments: vec![ast::PathSegment {
230-
identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")),
231-
parameters: ast::PathParameters::none(),
232-
}],
233-
},
234-
tts: def.body.clone(),
235-
}
236-
}),
237-
vis: ast::Visibility::Inherited,
238-
span: def.span,
239-
})))
215+
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
216+
mac
217+
}
240218
}

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010

1111
use {ast, attr};
1212
use syntax_pos::{Span, DUMMY_SP};
13-
use ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension};
14-
use ext::base::{IdentMacroExpander, NormalTT, TTMacroExpander};
13+
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
14+
use ext::base::{NormalTT, TTMacroExpander};
1515
use ext::expand::{Expansion, ExpansionKind};
16-
use ext::placeholders;
1716
use ext::tt::macro_parser::{Success, Error, Failure};
1817
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
1918
use ext::tt::macro_parser::{parse, parse_failure_msg};
@@ -151,35 +150,6 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
151150
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
152151
}
153152

154-
pub struct MacroRulesExpander;
155-
impl IdentMacroExpander for MacroRulesExpander {
156-
fn expand(&self,
157-
cx: &mut ExtCtxt,
158-
span: Span,
159-
ident: ast::Ident,
160-
tts: Vec<tokenstream::TokenTree>,
161-
attrs: Vec<ast::Attribute>)
162-
-> Box<MacResult> {
163-
let def = ast::MacroDef {
164-
ident: ident,
165-
id: ast::DUMMY_NODE_ID,
166-
span: span,
167-
body: tts,
168-
attrs: attrs,
169-
};
170-
171-
// If keep_macs is true, expands to a MacEager::items instead.
172-
let result = if cx.ecfg.keep_macs {
173-
MacEager::items(placeholders::reconstructed_macro_rules(&def).make_items())
174-
} else {
175-
MacEager::items(placeholders::macro_scope_placeholder().make_items())
176-
};
177-
178-
cx.resolver.add_macro(cx.current_expansion.mark, def);
179-
result
180-
}
181-
}
182-
183153
// Note that macro-by-example's input is also matched against a token tree:
184154
// $( $lhs:tt => $rhs:tt );+
185155
//

src/libsyntax_ext/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ pub mod deriving;
5050

5151
use std::rc::Rc;
5252
use syntax::ast;
53-
use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension};
54-
use syntax::ext::tt::macro_rules::MacroRulesExpander;
53+
use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension};
5554
use syntax::symbol::Symbol;
5655

5756
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
@@ -61,8 +60,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
6160
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
6261
};
6362

64-
register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
65-
6663
macro_rules! register {
6764
($( $name:ident: $f:expr, )*) => { $(
6865
register(Symbol::intern(stringify!($name)),

0 commit comments

Comments
 (0)