From 9fb11fe9f21051f4f03da55f949de402e78a95d5 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 25 Jul 2015 21:54:19 -0700 Subject: [PATCH] Extend macro machinery to expand macros in types Reapplied the changes from https://github.com/freebroccolo/rust/commit/7aafe24139abc2d1f302bbb166bcaa006f12cf4d to a clean branch of master --- src/libsyntax/ext/base.rs | 15 ++++++++++++ src/libsyntax/ext/expand.rs | 37 +++++++++++++++++++++++++++++ src/libsyntax/ext/tt/macro_rules.rs | 6 +++++ 3 files changed, 58 insertions(+) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 409ae86db35d..28c7ead20bca 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -290,6 +290,10 @@ pub trait MacResult { fn make_stmts(self: Box) -> Option>> { make_stmts_default!(self) } + + fn make_ty(self: Box) -> Option> { + None + } } macro_rules! make_MacEager { @@ -322,6 +326,7 @@ make_MacEager! { items: SmallVector>, impl_items: SmallVector>, stmts: SmallVector>, + ty: P, } impl MacResult for MacEager { @@ -359,6 +364,10 @@ impl MacResult for MacEager { } None } + + fn make_ty(self: Box) -> Option> { + self.ty + } } /// Fill-in macro expansion result, to allow compilation to continue @@ -405,6 +414,12 @@ impl DummyResult { } } + pub fn raw_ty(sp: Span) -> P { + P(ast::Ty { + id: ast:DUMMY_NODE_ID, + node: ast::TyInfer, + span: sp + }) } impl MacResult for DummyResult { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6e49b190f7c2..cd340fc91891 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1552,6 +1552,35 @@ fn expand_and_rename_method(sig: ast::MethodSig, body: P, }, rewritten_body) } +pub fn expand_type(t: P, fld: &mut MacroExpander) -> P { + let t = match t.node.clone() { + ast::Ty_::TyMac(mac) => { + let expanded_ty = match expand_mac_invoc(mac, t.span, + |r| r.make_ty(), + mark_ty, + fld) { + Some(ty) => ty, + None => { + return DummyResult::raw_ty(t.span); + } + }; + + // Keep going, outside-in. + // + let fully_expanded = fld.fold_ty(expanded_ty); + fld.cx.bt_pop(); + + fully_expanded.map(|t| ast::Ty { + id: ast::DUMMY_NODE_ID, + node: t.node, + span: t.span, + }) + } + _ => t + }; + fold::noop_fold_ty(t, fld) +} + /// A tree-folder that performs macro expansion pub struct MacroExpander<'a, 'b:'a> { pub cx: &'a mut ExtCtxt<'b>, @@ -1602,6 +1631,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { .into_iter().map(|i| i.expect_impl_item()).collect() } + fn fold_ty(&mut self, ty: P) -> P { + expand_type(ty, self) + } + fn new_span(&mut self, span: Span) -> Span { new_span(self.cx, span) } @@ -1748,6 +1781,10 @@ fn mark_impl_item(ii: P, m: Mrk) -> P { .expect_one("marking an impl item didn't return exactly one impl item") } +fn mark_ty(ty: P, m: Mrk) -> P { + Marker { mark: m }.fold_ty(ty) +} + /// Check that there are no macro invocations left in the AST: pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) { visit::walk_crate(&mut MacroExterminator{sess:sess}, krate); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index adc88c329a31..d16fde7bc394 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -117,6 +117,12 @@ impl<'a> MacResult for ParserAnyMacro<'a> { self.ensure_complete_parse(false); Some(ret) } + + fn make_ty(self: Box>) -> Option> { + let ret = self.parser.borrow_mut().parse_ty(); + self.ensure_complete_parse(true); + Some(ret) + } } struct MacroRulesMacroExpander {