diff options
| author | bors <bors@rust-lang.org> | 2015-08-06 19:11:17 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-08-06 19:11:17 +0000 |
| commit | 11deb083f5bc3e57e73fc82de4bef7b1d4dad7b1 (patch) | |
| tree | 0f575e98b114fe6b854a1fd53ff1f7749ba3621c /src/libsyntax/ext | |
| parent | fb92de75c1c4b7eaaf5d425fb2587407c00701fc (diff) | |
| parent | 83e43bb728b95d52039824d63b1ba5bbde5c5d7b (diff) | |
| download | rust-11deb083f5bc3e57e73fc82de4bef7b1d4dad7b1.tar.gz rust-11deb083f5bc3e57e73fc82de4bef7b1d4dad7b1.zip | |
Auto merge of #27296 - jroesch:type-macros, r=huonw
This pull request implements the functionality for [RFC 873](https://github.com/rust-lang/rfcs/blob/master/text/0873-type-macros.md). This is currently just an update of @freebroccolo's branch from January, the corresponding commits are linked in each commit message. @nikomatsakis and I had talked about updating the macro language to support a lifetime fragment specifier, and it is possible to do that work on this branch as well. If so we can (collectively) talk about it next week during the pre-RustCamp work week.
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 47 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 6 |
3 files changed, 73 insertions, 0 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b2cff3ed53c..d4b5e67eeb4 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,15 +414,24 @@ 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 { fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> { Some(DummyResult::raw_expr(self.span)) } + fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> { Some(P(DummyResult::raw_pat(self.span))) } + fn make_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Item>>> { // this code needs a comment... why not always just return the Some() ? if self.expr_only { @@ -422,6 +440,7 @@ impl MacResult for DummyResult { Some(SmallVector::zero()) } } + fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVector<P<ast::ImplItem>>> { if self.expr_only { None @@ -429,6 +448,7 @@ impl MacResult for DummyResult { Some(SmallVector::zero()) } } + fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<P<ast::Stmt>>> { Some(SmallVector::one(P( codemap::respan(self.span, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 66b3768a476..cd60ee0691c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1542,6 +1542,45 @@ 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) => { + if fld.cx.ecfg.features.unwrap().type_macros { + 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, + }) + } else { + feature_gate::emit_feature_err( + &fld.cx.parse_sess.span_diagnostic, + "type_macros", + t.span, + "type macros are experimental (see issue: #27336)"); + + DummyResult::raw_ty(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>, @@ -1592,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) } @@ -1744,6 +1787,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 { |
