Skip to content

Commit 397ed19

Browse files
authored
Rollup merge of rust-lang#48465 - abonander:expansion_order, r=petrochenkov
Expand items before their derives continuation of rust-lang#41029 At this point all I've done is naively rebased on top of `master` and fixed the code enough to compile. I'm not even sure if it works because my local build stopped here: ``` C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Microsoft.CppBuild.targets(317,5): error MSB3491: Could not write lines to file "emscripten -optimizer.dir\Release\emscript.63209ED8.tlog\emscripten-optimizer.lastbuildstate". The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. [C:\Users\cyber\Rust\rust\build\x86_64-pc-windows-msvc\stage0-rustc\x86_64-pc-windows-msvc\release\bui ld\rustc_binaryen-aaf5e3b308543526\out\build\src\emscripten-optimizer\emscripten-optimizer.vcxproj] ``` So I'm going to be relying on Travis to run tests unless I can fix this error.
2 parents 09e45bd + c6706ea commit 397ed19

File tree

12 files changed

+211
-113
lines changed

12 files changed

+211
-113
lines changed

src/librustc_resolve/macros.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
1818
use rustc::hir::def::{Def, Export};
1919
use rustc::hir::map::{self, DefCollector};
2020
use rustc::{ty, lint};
21-
use syntax::ast::{self, Name, Ident};
21+
use syntax::ast::{self, Name, Ident, Path};
2222
use syntax::attr::{self, HasAttrs};
2323
use syntax::codemap::respan;
2424
use syntax::errors::DiagnosticBuilder;
@@ -166,16 +166,25 @@ impl<'a> base::Resolver for Resolver<'a> {
166166
self.whitelisted_legacy_custom_derives.contains(&name)
167167
}
168168

169-
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
169+
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]) {
170170
let invocation = self.invocations[&mark];
171171
self.collect_def_ids(mark, invocation, expansion);
172172

173173
self.current_module = invocation.module.get();
174-
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
175-
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
176-
for &derive in derives {
177-
self.invocations.insert(derive, invocation);
174+
175+
{
176+
let mut unresolved = self.current_module.unresolved_invocations.borrow_mut();
177+
unresolved.remove(&mark);
178+
179+
unresolved.reserve(derives.len());
180+
self.invocations.reserve(derives.len());
181+
182+
for &(derive, _) in derives {
183+
unresolved.insert(derive);
184+
self.invocations.insert(derive, invocation);
185+
}
178186
}
187+
179188
let mut visitor = BuildReducedGraphVisitor {
180189
resolver: self,
181190
legacy_scope: LegacyScope::Invocation(invocation),

src/libsyntax/ext/base.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
pub use self::SyntaxExtension::*;
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, MultiSpan, DUMMY_SP};
@@ -615,7 +615,7 @@ pub trait Resolver {
615615
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
616616
fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
617617

618-
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
618+
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[(Mark, Path)]);
619619
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
620620

621621
fn resolve_imports(&mut self);
@@ -642,7 +642,9 @@ impl Resolver for DummyResolver {
642642
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
643643
fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
644644

645-
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
645+
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion,
646+
_derives: &[(Mark, Path)]) {}
647+
646648
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
647649

648650
fn resolve_imports(&mut self) {}

src/libsyntax/ext/expand.rs

Lines changed: 114 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ macro_rules! expansions {
4646
$(.$visit:ident)* $(lift .$visit_elt:ident)*;)*) => {
4747
#[derive(Copy, Clone, PartialEq, Eq)]
4848
pub enum ExpansionKind { OptExpr, $( $kind, )* }
49+
#[derive(Clone)]
4950
pub enum Expansion { OptExpr(Option<P<ast::Expr>>), $( $kind($ty), )* }
5051

5152
impl ExpansionKind {
@@ -210,12 +211,36 @@ impl Invocation {
210211

211212
pub struct MacroExpander<'a, 'b:'a> {
212213
pub cx: &'a mut ExtCtxt<'b>,
214+
partial_expansions: HashMap<Mark, PartialExpansion>,
215+
full_expansions: HashMap<Mark, FullExpansion>,
213216
monotonic: bool, // c.f. `cx.monotonic_expander()`
214217
}
215218

219+
220+
// jseyfried (10/04/2017):
221+
// Partial expansion are macro expansions that have unexpanded macro invocations in them.
222+
// That is, the macro itself has resolved and been expanded, but it created more macro invocations
223+
// that have yet to be expanded. This is in contrast to "fully expanded" AST,
224+
// which has no macro invocations left.
225+
struct PartialExpansion {
226+
expansion: Expansion,
227+
derives: Vec<(Mark, Path)>,
228+
expansion_kind: ExpansionKind,
229+
expansion_data: ExpansionData,
230+
unexpanded_children: usize,
231+
}
232+
233+
pub struct FullExpansion {
234+
pub expansion: Expansion,
235+
pub derives: Vec<Mark>,
236+
}
237+
216238
impl<'a, 'b> MacroExpander<'a, 'b> {
217239
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
218-
MacroExpander { cx: cx, monotonic: monotonic }
240+
MacroExpander {
241+
cx: cx, monotonic: monotonic,
242+
partial_expansions: HashMap::new(), full_expansions: HashMap::new(),
243+
}
219244
}
220245

221246
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
@@ -266,12 +291,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
266291
let orig_expansion_data = self.cx.current_expansion.clone();
267292
self.cx.current_expansion.depth = 0;
268293

269-
let (expansion, mut invocations) = self.collect_invocations(expansion, &[]);
294+
let mark = self.cx.current_expansion.mark;
295+
let mut invocations =
296+
self.collect_invocations(mark, expansion, Vec::new(), ExpansionKind::Items);
270297
self.resolve_imports();
271298
invocations.reverse();
272299

273-
let mut expansions = Vec::new();
274-
let mut derives = HashMap::new();
275300
let mut undetermined_invocations = Vec::new();
276301
let (mut progress, mut force) = (false, !self.monotonic);
277302
loop {
@@ -285,8 +310,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
285310
continue
286311
};
287312

288-
let scope =
289-
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
313+
let mark = invoc.expansion_data.mark;
314+
let scope = if self.monotonic { mark } else { orig_expansion_data.mark };
290315
let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
291316
Ok(ext) => Some(ext),
292317
Err(Determinacy::Determined) => None,
@@ -297,16 +322,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
297322
};
298323

299324
progress = true;
300-
let ExpansionData { depth, mark, .. } = invoc.expansion_data;
301325
self.cx.current_expansion = invoc.expansion_data.clone();
302326

303327
self.cx.current_expansion.mark = scope;
304-
// FIXME(jseyfried): Refactor out the following logic
305-
let (expansion, new_invocations) = if let Some(ext) = ext {
328+
let new_invocations = if let Some(ext) = ext {
306329
if let Some(ext) = ext {
330+
let expansion_kind = invoc.expansion_kind;
307331
let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
308332
let expansion = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
309-
self.collect_invocations(expansion, &[])
333+
self.collect_invocations(mark, expansion, Vec::new(), expansion_kind)
310334
} else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
311335
if !item.derive_allowed() {
312336
let attr = attr::find_by_name(item.attrs(), "derive")
@@ -326,60 +350,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
326350

327351
let item = self.fully_configure(item)
328352
.map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
329-
let item_with_markers =
330-
add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
331-
let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);
332-
333-
for path in &traits {
334-
let mark = Mark::fresh(self.cx.current_expansion.mark);
335-
derives.push(mark);
336-
let item = match self.cx.resolver.resolve_macro(
337-
Mark::root(), path, MacroKind::Derive, false) {
338-
Ok(ext) => match *ext {
339-
BuiltinDerive(..) => item_with_markers.clone(),
340-
_ => item.clone(),
341-
},
342-
_ => item.clone(),
343-
};
344-
invocations.push(Invocation {
345-
kind: InvocationKind::Derive { path: path.clone(), item: item },
346-
expansion_kind: invoc.expansion_kind,
347-
expansion_data: ExpansionData {
348-
mark,
349-
..invoc.expansion_data.clone()
350-
},
351-
});
352-
}
353+
let item = add_derived_markers(&mut self.cx, item.span(), &traits, item);
353354
let expansion = invoc.expansion_kind
354-
.expect_from_annotatables(::std::iter::once(item_with_markers));
355-
self.collect_invocations(expansion, derives)
355+
.expect_from_annotatables(::std::iter::once(item));
356+
self.collect_invocations(mark, expansion, traits, invoc.expansion_kind)
356357
} else {
357358
unreachable!()
358359
}
359360
} else {
360-
self.collect_invocations(invoc.expansion_kind.dummy(invoc.span()).unwrap(), &[])
361+
let dummy = invoc.expansion_kind.dummy(invoc.span()).unwrap();
362+
self.collect_invocations(mark, dummy, Vec::new(), invoc.expansion_kind)
361363
};
362364

363-
if expansions.len() < depth {
364-
expansions.push(Vec::new());
365-
}
366-
expansions[depth - 1].push((mark, expansion));
367365
if !self.cx.ecfg.single_step {
368366
invocations.extend(new_invocations.into_iter().rev());
369367
}
370368
}
371369

372370
self.cx.current_expansion = orig_expansion_data;
371+
self.placeholder_expander().remove(NodeId::placeholder_from_mark(mark))
372+
}
373373

374-
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
375-
while let Some(expansions) = expansions.pop() {
376-
for (mark, expansion) in expansions.into_iter().rev() {
377-
let derives = derives.remove(&mark).unwrap_or_else(Vec::new);
378-
placeholder_expander.add(NodeId::placeholder_from_mark(mark), expansion, derives);
379-
}
374+
fn placeholder_expander<'c>(&'c mut self) -> PlaceholderExpander<'c, 'b> {
375+
PlaceholderExpander {
376+
cx: self.cx,
377+
expansions: &mut self.full_expansions,
378+
monotonic: self.monotonic,
380379
}
381-
382-
expansion.fold_with(&mut placeholder_expander)
383380
}
384381

385382
fn resolve_imports(&mut self) {
@@ -390,30 +387,91 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
390387
}
391388
}
392389

393-
fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
394-
-> (Expansion, Vec<Invocation>) {
395-
let result = {
390+
fn collect_invocations(&mut self,
391+
mut mark: Mark,
392+
expansion: Expansion,
393+
traits: Vec<Path>,
394+
expansion_kind: ExpansionKind)
395+
-> Vec<Invocation> {
396+
let (expansion, mut invocations) = {
396397
let mut collector = InvocationCollector {
397398
cfg: StripUnconfigured {
398399
should_test: self.cx.ecfg.should_test,
399400
sess: self.cx.parse_sess,
400401
features: self.cx.ecfg.features,
401402
},
402403
cx: self.cx,
404+
mark: mark,
403405
invocations: Vec::new(),
404406
monotonic: self.monotonic,
405407
};
406408
(expansion.fold_with(&mut collector), collector.invocations)
407409
};
408410

411+
let mark_parent = mark.parent();
412+
let derives: Vec<_> =
413+
traits.into_iter().map(|path| (Mark::fresh(mark_parent), path)).collect();
414+
if derives.len() > 0 {
415+
self.partial_expansions.get_mut(&mark_parent).unwrap().unexpanded_children +=
416+
derives.len();
417+
}
418+
409419
if self.monotonic {
410420
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
411421
let mark = self.cx.current_expansion.mark;
412-
self.cx.resolver.visit_expansion(mark, &result.0, derives);
422+
self.cx.resolver.visit_expansion(mark, &expansion, &derives);
413423
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
414424
}
415425

416-
result
426+
self.partial_expansions.insert(mark, PartialExpansion {
427+
expansion: expansion, derives: derives, expansion_kind: expansion_kind,
428+
expansion_data: self.cx.current_expansion.clone(),
429+
unexpanded_children: invocations.len(),
430+
});
431+
432+
if !invocations.is_empty() {
433+
return invocations;
434+
}
435+
436+
loop {
437+
let partial_expansion = self.partial_expansions.remove(&mark).unwrap();
438+
let expansion = partial_expansion.expansion.fold_with(&mut self.placeholder_expander());
439+
440+
let PartialExpansion { expansion_kind, ref expansion_data, .. } = partial_expansion;
441+
let derives = partial_expansion.derives.into_iter().map(|(mark, path)| {
442+
let item = match expansion.clone() {
443+
Expansion::Items(mut items) => Annotatable::Item(items.pop().unwrap()),
444+
Expansion::TraitItems(mut items) =>
445+
Annotatable::TraitItem(P(items.pop().unwrap())),
446+
Expansion::ImplItems(mut items) =>
447+
Annotatable::ImplItem(P(items.pop().unwrap())),
448+
_ => panic!("expected item"),
449+
};
450+
invocations.push(Invocation {
451+
kind: InvocationKind::Derive { path: path, item: item },
452+
expansion_kind: expansion_kind,
453+
expansion_data: ExpansionData { mark: mark, ..expansion_data.clone() },
454+
});
455+
mark
456+
}).collect();
457+
458+
self.full_expansions
459+
.insert(mark, FullExpansion { expansion: expansion, derives: derives });
460+
461+
if mark == Mark::root() {
462+
break
463+
}
464+
mark = mark.parent();
465+
if let Some(partial_expansion) = self.partial_expansions.get_mut(&mark) {
466+
partial_expansion.unexpanded_children -= 1;
467+
if partial_expansion.unexpanded_children == 0 {
468+
continue
469+
}
470+
}
471+
break
472+
}
473+
474+
invocations
417475
}
418476

419477
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
@@ -793,14 +851,15 @@ impl<'a> Parser<'a> {
793851

794852
struct InvocationCollector<'a, 'b: 'a> {
795853
cx: &'a mut ExtCtxt<'b>,
854+
mark: Mark,
796855
cfg: StripUnconfigured<'a>,
797856
invocations: Vec<Invocation>,
798857
monotonic: bool,
799858
}
800859

801860
impl<'a, 'b> InvocationCollector<'a, 'b> {
802861
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
803-
let mark = Mark::fresh(self.cx.current_expansion.mark);
862+
let mark = Mark::fresh(self.mark);
804863
self.invocations.push(Invocation {
805864
kind,
806865
expansion_kind,
@@ -1180,7 +1239,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
11801239

11811240
fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
11821241
if self.monotonic {
1183-
assert_eq!(id, ast::DUMMY_NODE_ID);
11841242
self.cx.resolver.next_node_id()
11851243
} else {
11861244
id

0 commit comments

Comments
 (0)