From 9fb11fe9f21051f4f03da55f949de402e78a95d5 Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 25 Jul 2015 21:54:19 -0700 Subject: 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 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/libsyntax/ext/base.rs') 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) -> 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 { -- cgit 1.4.1-3-g733a5 From 8602a7d89843dcd7d41d2bb569817ddb760dbf7e Mon Sep 17 00:00:00 2001 From: Jared Roesch Date: Sat, 25 Jul 2015 22:17:43 -0700 Subject: Update and add test case Test case from here: https://github.com/freebroccolo/rust/commit/9e93fef3c0e61836a8b56f727eb7a2e94bb4ca09 --- src/librustc_typeck/astconv.rs | 2 +- src/libsyntax/ext/base.rs | 7 +++- src/test/run-pass/type-macros.rs | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/type-macros.rs (limited to 'src/libsyntax/ext/base.rs') diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cfd681e51f4..99f375c3286 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1663,7 +1663,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, this.ty_infer(None, None, None, ast_ty.span) } ast::TyMac(_) => { - tcx.sess.span_bug(m.span, "unexpanded type macro found conversion") + tcx.sess.span_bug(ast_ty.span, "unexpanded type macro found conversion") } }; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 28c7ead20bc..1b5dcf64833 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -416,19 +416,22 @@ impl DummyResult { pub fn raw_ty(sp: Span) -> P { P(ast::Ty { - id: ast:DUMMY_NODE_ID, + id: ast::DUMMY_NODE_ID, node: ast::TyInfer, span: sp }) + } } impl MacResult for DummyResult { fn make_expr(self: Box) -> Option> { Some(DummyResult::raw_expr(self.span)) } + fn make_pat(self: Box) -> Option> { Some(P(DummyResult::raw_pat(self.span))) } + fn make_items(self: Box) -> Option>> { // this code needs a comment... why not always just return the Some() ? if self.expr_only { @@ -437,6 +440,7 @@ impl MacResult for DummyResult { Some(SmallVector::zero()) } } + fn make_impl_items(self: Box) -> Option>> { if self.expr_only { None @@ -444,6 +448,7 @@ impl MacResult for DummyResult { Some(SmallVector::zero()) } } + fn make_stmts(self: Box) -> Option>> { Some(SmallVector::one(P( codemap::respan(self.span, diff --git a/src/test/run-pass/type-macros.rs b/src/test/run-pass/type-macros.rs new file mode 100644 index 00000000000..3ca3be8efed --- /dev/null +++ b/src/test/run-pass/type-macros.rs @@ -0,0 +1,82 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::*; + +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +struct Nil; // empty HList +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +struct Cons(H, T); // cons cell of HList + +// trait to classify valid HLists +trait HList {} +impl HList for Nil {} +impl HList for Cons {} + +// term-level macro for HLists +macro_rules! hlist { + {} => { Nil }; + { $head:expr } => { Cons($head, Nil) }; + { $head:expr, $($tail:expr),* } => { Cons($head, hlist!($($tail),*)) }; +} + +// type-level macro for HLists +macro_rules! HList { + {} => { Nil }; + { $head:ty } => { Cons<$head, Nil> }; + { $head:ty, $($tail:ty),* } => { Cons<$head, HList!($($tail),*)> }; +} + +// nil case for HList append +impl Add for Nil { + type Output = Ys; + + fn add(self, rhs: Ys) -> Ys { + rhs + } +} + +// cons case for HList append +impl Add for Cons where + Xs: Add, +{ + type Output = Cons; + + fn add(self, rhs: Ys) -> Cons { + Cons(self.0, self.1 + rhs) + } +} + +// type macro Expr allows us to expand the + operator appropriately +macro_rules! Expr { + { ( $($LHS:tt)+ ) } => { Expr!($($LHS)+) }; + { HList ! [ $($LHS:tt)* ] + $($RHS:tt)+ } => { >::Output }; + { $LHS:tt + $($RHS:tt)+ } => { >::Output }; + { $LHS:ty } => { $LHS }; +} + +// test demonstrating term level `xs + ys` and type level `Expr!(Xs + Ys)` +fn main() { + fn aux(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) + where Xs: Add { + xs + ys + } + + let xs: HList![&str, bool, Vec] = hlist!["foo", false, vec![]]; + let ys: HList![u64, [u8; 3], ()] = hlist![0, [0, 1, 2], ()]; + + // demonstrate recursive expansion of Expr! + let zs: Expr!((HList![&str] + HList![bool] + HList![Vec]) + + (HList![u64] + HList![[u8; 3], ()]) + + HList![]) + = aux(xs, ys); + assert_eq!(zs, hlist!["foo", false, vec![], 0, [0, 1, 2], ()]) +} + -- cgit 1.4.1-3-g733a5