about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorJared Roesch <roeschinc@gmail.com>2015-07-25 21:54:19 -0700
committerJared Roesch <roeschinc@gmail.com>2015-08-04 16:05:06 -0700
commit9fb11fe9f21051f4f03da55f949de402e78a95d5 (patch)
treed9ae7e953684d3d6558fb45c4f85211481dd208a /src/libsyntax/ext
parentedca562c87362c80e409f53d28e19617ca44646a (diff)
downloadrust-9fb11fe9f21051f4f03da55f949de402e78a95d5.tar.gz
rust-9fb11fe9f21051f4f03da55f949de402e78a95d5.zip
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
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs15
-rw-r--r--src/libsyntax/ext/expand.rs37
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs6
3 files changed, 58 insertions, 0 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 409ae86db35..28c7ead20bc 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<Self>) -> Option<SmallVector<P<ast::Stmt>>> {
         make_stmts_default!(self)
     }
+
+    fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
+        None
+    }
 }
 
 macro_rules! make_MacEager {
@@ -322,6 +326,7 @@ make_MacEager! {
     items: SmallVector<P<ast::Item>>,
     impl_items: SmallVector<P<ast::ImplItem>>,
     stmts: SmallVector<P<ast::Stmt>>,
+    ty: P<ast::Ty>,
 }
 
 impl MacResult for MacEager {
@@ -359,6 +364,10 @@ impl MacResult for MacEager {
         }
         None
     }
+
+    fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
+        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<ast::Ty> {
+        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 6e49b190f7c..cd340fc9189 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<ast::Block>,
     }, rewritten_body)
 }
 
+pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
+    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<ast::Ty>) -> P<ast::Ty> {
+        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<ast::ImplItem>, m: Mrk) -> P<ast::ImplItem> {
         .expect_one("marking an impl item didn't return exactly one impl item")
 }
 
+fn mark_ty(ty: P<ast::Ty>, m: Mrk) -> P<ast::Ty> {
+    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 adc88c329a3..d16fde7bc39 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<ParserAnyMacro<'a>>) -> Option<P<ast::Ty>> {
+        let ret = self.parser.borrow_mut().parse_ty();
+        self.ensure_complete_parse(true);
+        Some(ret)
+    }
 }
 
 struct MacroRulesMacroExpander {