Skip to content

Commit df1405d

Browse files
committed
Expand items before their #[derive]s.
1 parent 5309a3e commit df1405d

File tree

13 files changed

+167
-117
lines changed

13 files changed

+167
-117
lines changed

src/librustc/hir/lowering.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl<'a> LoweringContext<'a> {
393393
}
394394

395395
fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
396-
let mark = Mark::fresh();
396+
let mark = Mark::fresh(Mark::root());
397397
mark.set_expn_info(codemap::ExpnInfo {
398398
call_site: span,
399399
callee: codemap::NameAndSpan {

src/librustc_resolve/macros.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}
1717
use rustc::hir::def::{Def, Export};
1818
use rustc::hir::map::{self, DefCollector};
1919
use rustc::ty;
20-
use syntax::ast::{self, Name, Ident};
20+
use syntax::ast::{self, Name, Ident, Path};
2121
use syntax::attr::{self, HasAttrs};
2222
use syntax::errors::DiagnosticBuilder;
2323
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
@@ -110,7 +110,7 @@ impl<'a> base::Resolver for Resolver<'a> {
110110
}
111111

112112
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
113-
let mark = Mark::fresh();
113+
let mark = Mark::fresh(Mark::root());
114114
let module = self.module_map[&self.definitions.local_def_id(id)];
115115
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
116116
module: Cell::new(module),
@@ -156,16 +156,20 @@ impl<'a> base::Resolver for Resolver<'a> {
156156
self.whitelisted_legacy_custom_derives.contains(&name)
157157
}
158158

159-
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
159+
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]) {
160160
let invocation = self.invocations[&mark];
161161
self.collect_def_ids(invocation, expansion);
162162

163163
self.current_module = invocation.module.get();
164-
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
165-
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
166-
for &derive in derives {
167-
self.invocations.insert(derive, invocation);
164+
{
165+
let mut unresolved = self.current_module.unresolved_invocations.borrow_mut();
166+
unresolved.remove(&mark);
167+
for &(derive, _) in derives {
168+
unresolved.insert(derive);
169+
self.invocations.insert(derive, invocation);
170+
}
168171
}
172+
169173
let mut visitor = BuildReducedGraphVisitor {
170174
resolver: self,
171175
legacy_scope: LegacyScope::Invocation(invocation),

src/libsyntax/ext/base.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
pub use self::SyntaxExtension::{MultiDecorator, MultiModifier, NormalTT, IdentTT};
1212

13-
use ast::{self, Attribute, Name, PatKind, MetaItem};
13+
use ast::{self, Attribute, Name, PatKind, MetaItem, Path};
1414
use attr::HasAttrs;
1515
use codemap::{self, CodeMap, Spanned, respan};
1616
use syntax_pos::{Span, DUMMY_SP};
@@ -578,7 +578,7 @@ pub trait Resolver {
578578
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
579579
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
580580

581-
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
581+
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]);
582582
fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
583583

584584
fn resolve_imports(&mut self);
@@ -604,7 +604,7 @@ impl Resolver for DummyResolver {
604604
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
605605
fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
606606

607-
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
607+
fn visit_expansion(&mut self, _invoc: Mark, _: &Expansion, _derives: &[(Mark, Path)]) {}
608608
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
609609

610610
fn resolve_imports(&mut self) {}

src/libsyntax/ext/expand.rs

+108-56
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ macro_rules! expansions {
4444
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
4545
#[derive(Copy, Clone, PartialEq, Eq)]
4646
pub enum ExpansionKind { OptExpr, $( $kind, )* }
47+
#[derive(Clone)]
4748
pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
4849

4950
impl ExpansionKind {
@@ -188,12 +189,30 @@ impl Invocation {
188189

189190
pub struct MacroExpander<'a, 'b:'a> {
190191
pub cx: &'a mut ExtCtxt<'b>,
192+
partial_expansions: HashMap<Mark, PartialExpansion>,
193+
full_expansions: HashMap<Mark, FullExpansion>,
191194
monotonic: bool, // c.f. `cx.monotonic_expander()`
192195
}
193196

197+
struct PartialExpansion {
198+
expansion: Expansion,
199+
derives: Vec<(Mark, Path)>,
200+
expansion_kind: ExpansionKind,
201+
expansion_data: ExpansionData,
202+
unexpanded_children: usize,
203+
}
204+
205+
pub struct FullExpansion {
206+
pub expansion: Expansion,
207+
pub derives: Vec<Mark>,
208+
}
209+
194210
impl<'a, 'b> MacroExpander<'a, 'b> {
195211
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
196-
MacroExpander { cx: cx, monotonic: monotonic }
212+
MacroExpander {
213+
cx: cx, monotonic: monotonic,
214+
partial_expansions: HashMap::new(), full_expansions: HashMap::new(),
215+
}
197216
}
198217

199218
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
@@ -230,12 +249,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
230249
let orig_expansion_data = self.cx.current_expansion.clone();
231250
self.cx.current_expansion.depth = 0;
232251

233-
let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
252+
let mark = self.cx.current_expansion.mark;
253+
let mut invocations =
254+
self.collect_invocations(mark, expansion, Vec::new(), ExpansionKind::Items);
234255
self.resolve_imports();
235256
invocations.reverse();
236257

237-
let mut expansions = Vec::new();
238-
let mut derives = HashMap::new();
239258
let mut undetermined_invocations = Vec::new();
240259
let (mut progress, mut force) = (false, !self.monotonic);
241260
loop {
@@ -249,8 +268,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
249268
continue
250269
};
251270

252-
let scope =
253-
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
271+
let mark = invoc.expansion_data.mark;
272+
let scope = if self.monotonic { mark } else { orig_expansion_data.mark };
254273
let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
255274
Ok(ext) => Some(ext),
256275
Err(Determinacy::Determined) => None,
@@ -261,72 +280,44 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
261280
};
262281

263282
progress = true;
264-
let ExpansionData { depth, mark, .. } = invoc.expansion_data;
265283
self.cx.current_expansion = invoc.expansion_data.clone();
266284

267285
self.cx.current_expansion.mark = scope;
268-
// FIXME(jseyfried): Refactor out the following logic
269-
let (expansion, new_invocations) = if let Some(ext) = ext {
286+
let new_invocations = if let Some(ext) = ext {
270287
if let Some(ext) = ext {
288+
let expansion_kind = invoc.expansion_kind;
271289
let expansion = self.expand_invoc(invoc, ext);
272-
self.collect_invocations(expansion, &[])
290+
self.collect_invocations(mark, expansion, Vec::new(), expansion_kind)
273291
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
274292
let item = item
275293
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
276-
let item_with_markers =
277-
add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
278-
let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);
279-
280-
for path in &traits {
281-
let mark = Mark::fresh();
282-
derives.push(mark);
283-
let item = match self.cx.resolver.resolve_macro(
284-
Mark::root(), path, MacroKind::Derive, false) {
285-
Ok(ext) => match *ext {
286-
SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(),
287-
_ => item.clone(),
288-
},
289-
_ => item.clone(),
290-
};
291-
invocations.push(Invocation {
292-
kind: InvocationKind::Derive { path: path.clone(), item: item },
293-
expansion_kind: invoc.expansion_kind,
294-
expansion_data: ExpansionData {
295-
mark: mark,
296-
..invoc.expansion_data.clone()
297-
},
298-
});
299-
}
294+
let item = add_derived_markers(&mut self.cx, item.span(), &traits, item);
300295
let expansion = invoc.expansion_kind
301-
.expect_from_annotatables(::std::iter::once(item_with_markers));
302-
self.collect_invocations(expansion, derives)
296+
.expect_from_annotatables(::std::iter::once(item));
297+
self.collect_invocations(mark, expansion, traits, invoc.expansion_kind)
303298
} else {
304299
unreachable!()
305300
}
306301
} else {
307-
self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()), &[])
302+
let dummy = invoc.expansion_kind.dummy(invoc.span());
303+
self.collect_invocations(mark, dummy, Vec::new(), invoc.expansion_kind)
308304
};
309305

310-
if expansions.len() < depth {
311-
expansions.push(Vec::new());
312-
}
313-
expansions[depth - 1].push((mark, expansion));
314306
if !self.cx.ecfg.single_step {
315307
invocations.extend(new_invocations.into_iter().rev());
316308
}
317309
}
318310

319311
self.cx.current_expansion = orig_expansion_data;
312+
self.placeholder_expander().remove(NodeId::placeholder_from_mark(mark))
313+
}
320314

321-
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
322-
while let Some(expansions) = expansions.pop() {
323-
for (mark, expansion) in expansions.into_iter().rev() {
324-
let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
325-
placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
326-
}
315+
fn placeholder_expander<'c>(&'c mut self) -> PlaceholderExpander<'c, 'b> {
316+
PlaceholderExpander {
317+
cx: self.cx,
318+
expansions: &mut self.full_expansions,
319+
monotonic: self.monotonic,
327320
}
328-
329-
expansion.fold_with(&mut placeholder_expander)
330321
}
331322

332323
fn resolve_imports(&mut self) {
@@ -337,30 +328,91 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
337328
}
338329
}
339330

340-
fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
341-
-> (Expansion, Vec<Invocation>) {
342-
let result = {
331+
fn collect_invocations(&mut self,
332+
mut mark: Mark,
333+
expansion: Expansion,
334+
traits: Vec<Path>,
335+
expansion_kind: ExpansionKind)
336+
-> Vec<Invocation> {
337+
let (expansion, mut invocations) = {
343338
let mut collector = InvocationCollector {
344339
cfg: StripUnconfigured {
345340
should_test: self.cx.ecfg.should_test,
346341
sess: self.cx.parse_sess,
347342
features: self.cx.ecfg.features,
348343
},
349344
cx: self.cx,
345+
mark: mark,
350346
invocations: Vec::new(),
351347
monotonic: self.monotonic,
352348
};
353349
(expansion.fold_with(&mut collector), collector.invocations)
354350
};
355351

352+
let mark_parent = mark.parent();
353+
let derives: Vec<_> =
354+
traits.into_iter().map(|path| (Mark::fresh(mark_parent), path)).collect();
355+
if derives.len() > 0 {
356+
self.partial_expansions.get_mut(&mark_parent).unwrap().unexpanded_children +=
357+
derives.len();
358+
}
359+
356360
if self.monotonic {
357361
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
358362
let mark = self.cx.current_expansion.mark;
359-
self.cx.resolver.visit_expansion(mark, &result.0, derives);
363+
self.cx.resolver.visit_expansion(mark, &expansion, &derives);
360364
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
361365
}
362366

363-
result
367+
self.partial_expansions.insert(mark, PartialExpansion {
368+
expansion: expansion, derives: derives, expansion_kind: expansion_kind,
369+
expansion_data: self.cx.current_expansion.clone(),
370+
unexpanded_children: invocations.len(),
371+
});
372+
373+
if !invocations.is_empty() {
374+
return invocations;
375+
}
376+
377+
loop {
378+
let partial_expansion = self.partial_expansions.remove(&mark).unwrap();
379+
let expansion = partial_expansion.expansion.fold_with(&mut self.placeholder_expander());
380+
381+
let PartialExpansion { expansion_kind, ref expansion_data, .. } = partial_expansion;
382+
let derives = partial_expansion.derives.into_iter().map(|(mark, path)| {
383+
let item = match expansion.clone() {
384+
Expansion::Items(mut items) => Annotatable::Item(items.pop().unwrap()),
385+
Expansion::TraitItems(mut items) =>
386+
Annotatable::TraitItem(P(items.pop().unwrap())),
387+
Expansion::ImplItems(mut items) =>
388+
Annotatable::ImplItem(P(items.pop().unwrap())),
389+
_ => panic!("expected item"),
390+
};
391+
invocations.push(Invocation {
392+
kind: InvocationKind::Derive { path: path, item: item },
393+
expansion_kind: expansion_kind,
394+
expansion_data: ExpansionData { mark: mark, ..expansion_data.clone() },
395+
});
396+
mark
397+
}).collect();
398+
399+
self.full_expansions
400+
.insert(mark, FullExpansion { expansion: expansion, derives: derives });
401+
402+
if mark == Mark::root() {
403+
break
404+
}
405+
mark = mark.parent();
406+
if let Some(partial_expansion) = self.partial_expansions.get_mut(&mark) {
407+
partial_expansion.unexpanded_children -= 1;
408+
if partial_expansion.unexpanded_children == 0 {
409+
continue
410+
}
411+
}
412+
break
413+
}
414+
415+
invocations
364416
}
365417

366418
fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
@@ -661,6 +713,7 @@ impl<'a> Parser<'a> {
661713

662714
struct InvocationCollector<'a, 'b: 'a> {
663715
cx: &'a mut ExtCtxt<'b>,
716+
mark: Mark,
664717
cfg: StripUnconfigured<'a>,
665718
invocations: Vec<Invocation>,
666719
monotonic: bool,
@@ -677,7 +730,7 @@ macro_rules! fully_configure {
677730

678731
impl<'a, 'b> InvocationCollector<'a, 'b> {
679732
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
680-
let mark = Mark::fresh();
733+
let mark = Mark::fresh(self.mark);
681734
self.invocations.push(Invocation {
682735
kind: kind,
683736
expansion_kind: expansion_kind,
@@ -992,7 +1045,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
9921045

9931046
fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
9941047
if self.monotonic {
995-
assert_eq!(id, ast::DUMMY_NODE_ID);
9961048
self.cx.resolver.next_node_id()
9971049
} else {
9981050
id

0 commit comments

Comments
 (0)