]> git.lizzy.rs Git - rust.git/commitdiff
Improve the `TokenStream` quoter.
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Tue, 14 Mar 2017 22:04:46 +0000 (22:04 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Wed, 15 Mar 2017 23:05:02 +0000 (23:05 +0000)
src/libproc_macro_plugin/lib.rs
src/libproc_macro_plugin/qquote.rs [deleted file]
src/libproc_macro_plugin/quote.rs [new file with mode: 0644]
src/libsyntax/tokenstream.rs
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/hello_macro.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/macro-quote-1.rs
src/test/run-pass-fulldeps/macro-quote-empty-delims.rs [deleted file]
src/test/run-pass-fulldeps/macro-quote-test.rs [new file with mode: 0644]

index e904290957619cbb8f8d0c3d87f3c042c740e420..a6dad64125331cc4c6ab5d903615fffbe8be4389 100644 (file)
 //! A library for procedural macro writers.
 //!
 //! ## Usage
-//! This crate provides the `qquote!` macro for syntax creation.
+//! This crate provides the `quote!` macro for syntax creation.
 //!
-//! The `qquote!` macro uses the crate `syntax`, so users must declare `extern crate syntax;`
+//! The `quote!` macro uses the crate `syntax`, so users must declare `extern crate syntax;`
 //! at the crate root. This is a temporary solution until we have better hygiene.
 //!
 //! ## Quasiquotation
 //!
 //! The quasiquoter creates output that, when run, constructs the tokenstream specified as
-//! input. For example, `qquote!(5 + 5)` will produce a program, that, when run, will
+//! input. For example, `quote!(5 + 5)` will produce a program, that, when run, will
 //! construct the TokenStream `5 | + | 5`.
 //!
 //! ### Unquoting
 //!
-//! Unquoting is currently done as `unquote`, and works by taking the single next
-//! TokenTree in the TokenStream as the unquoted term. Ergonomically, `unquote(foo)` works
-//! fine, but `unquote foo` is also supported.
+//! Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
+//! To quote `$` itself, use `$$`.
 //!
-//! A simple example might be:
+//! A simple example is:
 //!
 //!```
 //!fn double(tmp: TokenStream) -> TokenStream {
-//!    qquote!(unquote(tmp) * 2)
+//!    quote!($tmp * 2)
 //!}
 //!```
 //!
-//! ### Large Example: Implementing Scheme's `cond`
+//! ### Large example: Scheme's `cond`
 //!
-//! Below is the full implementation of Scheme's `cond` operator.
+//! Below is an example implementation of Scheme's `cond`.
 //!
 //! ```
-//! fn cond_rec(input: TokenStream) -> TokenStream {
-//!   if input.is_empty() { return quote!(); }
-//!
-//!   let next = input.slice(0..1);
-//!   let rest = input.slice_from(1..);
-//!
-//!   let clause : TokenStream = match next.maybe_delimited() {
-//!     Some(ts) => ts,
-//!     _ => panic!("Invalid input"),
-//!   };
-//!
-//!   // clause is ([test]) [rhs]
-//!   if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
-//!
-//!   let test: TokenStream = clause.slice(0..1);
-//!   let rhs: TokenStream = clause.slice_from(1..);
-//!
-//!   if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
-//!     quote!({unquote(rhs)})
-//!   } else {
-//!     quote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
-//!   }
+//! fn cond(input: TokenStream) -> TokenStream {
+//!     let mut conds = Vec::new();
+//!     let mut input = input.trees().peekable();
+//!     while let Some(tree) = input.next() {
+//!         let mut cond = match tree {
+//!             TokenTree::Delimited(_, ref delimited) => delimited.stream(),
+//!             _ => panic!("Invalid input"),
+//!         };
+//!         let mut trees = cond.trees();
+//!         let test = trees.next();
+//!         let rhs = trees.collect::<TokenStream>();
+//!         if rhs.is_empty() {
+//!             panic!("Invalid macro usage in cond: {}", cond);
+//!         }
+//!         let is_else = match test {
+//!             Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true,
+//!             _ => false,
+//!         };
+//!         conds.push(if is_else || input.peek().is_none() {
+//!             quote!({ $rhs })
+//!         } else {
+//!             let test = test.unwrap();
+//!             quote!(if $test { $rhs } else)
+//!         });
+//!     }
+//!
+//!     conds.into_iter().collect()
 //! }
 //! ```
-//!
-
 #![crate_name = "proc_macro_plugin"]
 #![unstable(feature = "rustc_private", issue = "27812")]
 #![feature(plugin_registrar)]
@@ -87,8 +89,8 @@
 extern crate syntax;
 extern crate syntax_pos;
 
-mod qquote;
-use qquote::qquote;
+mod quote;
+use quote::quote;
 
 use rustc_plugin::Registry;
 use syntax::ext::base::SyntaxExtension;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_syntax_extension(Symbol::intern("qquote"),
-                                  SyntaxExtension::ProcMacro(Box::new(qquote)));
+    reg.register_syntax_extension(Symbol::intern("quote"),
+                                  SyntaxExtension::ProcMacro(Box::new(quote)));
 }
diff --git a/src/libproc_macro_plugin/qquote.rs b/src/libproc_macro_plugin/qquote.rs
deleted file mode 100644 (file)
index 0276587..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2016 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! # Quasiquoter
-//! This file contains the implementation internals of the quasiquoter provided by `qquote!`.
-
-use syntax::ast::Ident;
-use syntax::parse::token::{self, Token, Lit};
-use syntax::symbol::Symbol;
-use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
-use syntax_pos::DUMMY_SP;
-
-use std::iter;
-
-pub fn qquote<'cx>(stream: TokenStream) -> TokenStream {
-    stream.quote()
-}
-
-trait Quote {
-    fn quote(&self) -> TokenStream;
-}
-
-macro_rules! quote_tok {
-    (,) => { Token::Comma };
-    (.) => { Token::Dot };
-    (:) => { Token::Colon };
-    (::) => { Token::ModSep };
-    (!) => { Token::Not };
-    (<) => { Token::Lt };
-    (>) => { Token::Gt };
-    (_) => { Token::Underscore };
-    ($i:ident) => { Token::Ident(Ident::from_str(stringify!($i))) };
-}
-
-macro_rules! quote_tree {
-    ((unquote $($t:tt)*)) => { $($t)* };
-    ((quote $($t:tt)*)) => { ($($t)*).quote() };
-    (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) };
-    ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) };
-    ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) };
-    ($t:tt) => { TokenStream::from(TokenTree::Token(DUMMY_SP, quote_tok!($t))) };
-}
-
-fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream {
-    TokenTree::Delimited(DUMMY_SP, Delimited { delim: delim, tts: stream.into() }).into()
-}
-
-macro_rules! quote {
-    () => { TokenStream::empty() };
-    ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::<TokenStream>() };
-}
-
-impl<T: Quote> Quote for Option<T> {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            Some(ref t) => quote!(::std::option::Option::Some((quote t))),
-            None => quote!(::std::option::Option::None),
-        }
-    }
-}
-
-impl Quote for TokenStream {
-    fn quote(&self) -> TokenStream {
-        if self.is_empty() {
-            return quote!(::syntax::tokenstream::TokenStream::empty());
-        }
-
-        struct Quote(iter::Peekable<tokenstream::Cursor>);
-
-        impl Iterator for Quote {
-            type Item = TokenStream;
-
-            fn next(&mut self) -> Option<TokenStream> {
-                let is_unquote = match self.0.peek() {
-                    Some(&TokenTree::Token(_, Token::Ident(ident))) if ident.name == "unquote" => {
-                        self.0.next();
-                        true
-                    }
-                    _ => false,
-                };
-
-                self.0.next().map(|tree| {
-                    let quoted_tree = if is_unquote { tree.into() } else { tree.quote() };
-                    quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),)
-                })
-            }
-        }
-
-        let quoted = Quote(self.trees().peekable()).collect::<TokenStream>();
-        quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
-    }
-}
-
-impl Quote for TokenTree {
-    fn quote(&self) -> TokenStream {
-        match *self {
-            TokenTree::Token(_, ref token) => quote! {
-                ::syntax::tokenstream::TokenTree::Token(::syntax::ext::quote::rt::DUMMY_SP,
-                                                        (quote token))
-            },
-            TokenTree::Delimited(_, ref delimited) => quote! {
-                ::syntax::tokenstream::TokenTree::Delimited(::syntax::ext::quote::rt::DUMMY_SP,
-                                                            (quote delimited))
-            },
-        }
-    }
-}
-
-impl Quote for Delimited {
-    fn quote(&self) -> TokenStream {
-        quote!(::syntax::tokenstream::Delimited {
-            delim: (quote self.delim),
-            tts: (quote self.stream()).into(),
-        })
-    }
-}
-
-impl<'a> Quote for &'a str {
-    fn quote(&self) -> TokenStream {
-        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None))
-            .into()
-    }
-}
-
-impl Quote for Ident {
-    fn quote(&self) -> TokenStream {
-        // FIXME(jseyfried) quote hygiene
-        quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str())))
-    }
-}
-
-impl Quote for Symbol {
-    fn quote(&self) -> TokenStream {
-        quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str())))
-    }
-}
-
-impl Quote for Token {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*; $($t:tt)*) => {
-                match *self {
-                    $( Token::$i => quote!(::syntax::parse::token::$i), )*
-                    $( $t )*
-                }
-            }
-        }
-
-        gen_match! {
-            Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
-            Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
-            Underscore;
-
-            Token::OpenDelim(delim) => quote!(::syntax::parse::token::OpenDelim((quote delim))),
-            Token::CloseDelim(delim) => quote!(::syntax::parse::token::CloseDelim((quote delim))),
-            Token::BinOp(tok) => quote!(::syntax::parse::token::BinOp((quote tok))),
-            Token::BinOpEq(tok) => quote!(::syntax::parse::token::BinOpEq((quote tok))),
-            Token::Ident(ident) => quote!(::syntax::parse::token::Ident((quote ident))),
-            Token::Lifetime(ident) => quote!(::syntax::parse::token::Lifetime((quote ident))),
-            Token::Literal(lit, sfx) => quote! {
-                ::syntax::parse::token::Literal((quote lit), (quote sfx))
-            },
-            _ => panic!("Unhandled case!"),
-        }
-    }
-}
-
-impl Quote for token::BinOpToken {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $( token::BinOpToken::$i => quote!(::syntax::parse::token::BinOpToken::$i), )*
-                }
-            }
-        }
-
-        gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr)
-    }
-}
-
-impl Quote for Lit {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )*
-                    _ => panic!("Unsupported literal"),
-                }
-            }
-        }
-
-        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr)
-    }
-}
-
-impl Quote for token::DelimToken {
-    fn quote(&self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match *self {
-                    $(token::DelimToken::$i => { quote!(::syntax::parse::token::DelimToken::$i) })*
-                }
-            }
-        }
-
-        gen_match!(Paren, Bracket, Brace, NoDelim)
-    }
-}
diff --git a/src/libproc_macro_plugin/quote.rs b/src/libproc_macro_plugin/quote.rs
new file mode 100644 (file)
index 0000000..ad71584
--- /dev/null
@@ -0,0 +1,220 @@
+// Copyright 2016 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! # Quasiquoter
+//! This file contains the implementation internals of the quasiquoter provided by `qquote!`.
+
+use syntax::ast::Ident;
+use syntax::parse::token::{self, Token, Lit};
+use syntax::symbol::Symbol;
+use syntax::tokenstream::{self, Delimited, TokenTree, TokenStream};
+use syntax_pos::DUMMY_SP;
+
+use std::iter;
+
+pub fn quote<'cx>(stream: TokenStream) -> TokenStream {
+    stream.quote()
+}
+
+trait Quote {
+    fn quote(&self) -> TokenStream;
+}
+
+macro_rules! quote_tok {
+    (,) => { Token::Comma };
+    (.) => { Token::Dot };
+    (:) => { Token::Colon };
+    (::) => { Token::ModSep };
+    (!) => { Token::Not };
+    (<) => { Token::Lt };
+    (>) => { Token::Gt };
+    (_) => { Token::Underscore };
+    ($i:ident) => { Token::Ident(Ident::from_str(stringify!($i))) };
+}
+
+macro_rules! quote_tree {
+    ((unquote $($t:tt)*)) => { $($t)* };
+    ((quote $($t:tt)*)) => { ($($t)*).quote() };
+    (($($t:tt)*)) => { delimit(token::Paren, quote!($($t)*)) };
+    ([$($t:tt)*]) => { delimit(token::Bracket, quote!($($t)*)) };
+    ({$($t:tt)*}) => { delimit(token::Brace, quote!($($t)*)) };
+    ($t:tt) => { TokenStream::from(TokenTree::Token(DUMMY_SP, quote_tok!($t))) };
+}
+
+fn delimit(delim: token::DelimToken, stream: TokenStream) -> TokenStream {
+    TokenTree::Delimited(DUMMY_SP, Delimited { delim: delim, tts: stream.into() }).into()
+}
+
+macro_rules! quote {
+    () => { TokenStream::empty() };
+    ($($t:tt)*) => { [ $( quote_tree!($t), )* ].iter().cloned().collect::<TokenStream>() };
+}
+
+impl<T: Quote> Quote for Option<T> {
+    fn quote(&self) -> TokenStream {
+        match *self {
+            Some(ref t) => quote!(::std::option::Option::Some((quote t))),
+            None => quote!(::std::option::Option::None),
+        }
+    }
+}
+
+impl Quote for TokenStream {
+    fn quote(&self) -> TokenStream {
+        if self.is_empty() {
+            return quote!(::syntax::tokenstream::TokenStream::empty());
+        }
+
+        struct Quoter(iter::Peekable<tokenstream::Cursor>);
+
+        impl Iterator for Quoter {
+            type Item = TokenStream;
+
+            fn next(&mut self) -> Option<TokenStream> {
+                let quoted_tree = if let Some(&TokenTree::Token(_, Token::Dollar)) = self.0.peek() {
+                    self.0.next();
+                    match self.0.next() {
+                        Some(tree @ TokenTree::Token(_, Token::Ident(..))) => Some(tree.into()),
+                        Some(tree @ TokenTree::Token(_, Token::Dollar)) => Some(tree.quote()),
+                        // FIXME(jseyfried): improve these diagnostics
+                        Some(..) => panic!("`$` must be followed by an ident or `$` in `quote!`"),
+                        None => panic!("unexpected trailing `$` in `quote!`"),
+                    }
+                } else {
+                    self.0.next().as_ref().map(Quote::quote)
+                };
+
+                quoted_tree.map(|quoted_tree| {
+                    quote!(::syntax::tokenstream::TokenStream::from((unquote quoted_tree)),)
+                })
+            }
+        }
+
+        let quoted = Quoter(self.trees().peekable()).collect::<TokenStream>();
+        quote!([(unquote quoted)].iter().cloned().collect::<::syntax::tokenstream::TokenStream>())
+    }
+}
+
+impl Quote for TokenTree {
+    fn quote(&self) -> TokenStream {
+        match *self {
+            TokenTree::Token(_, ref token) => quote! {
+                ::syntax::tokenstream::TokenTree::Token(::syntax::ext::quote::rt::DUMMY_SP,
+                                                        (quote token))
+            },
+            TokenTree::Delimited(_, ref delimited) => quote! {
+                ::syntax::tokenstream::TokenTree::Delimited(::syntax::ext::quote::rt::DUMMY_SP,
+                                                            (quote delimited))
+            },
+        }
+    }
+}
+
+impl Quote for Delimited {
+    fn quote(&self) -> TokenStream {
+        quote!(::syntax::tokenstream::Delimited {
+            delim: (quote self.delim),
+            tts: (quote self.stream()).into(),
+        })
+    }
+}
+
+impl<'a> Quote for &'a str {
+    fn quote(&self) -> TokenStream {
+        TokenTree::Token(DUMMY_SP, Token::Literal(token::Lit::Str_(Symbol::intern(self)), None))
+            .into()
+    }
+}
+
+impl Quote for Ident {
+    fn quote(&self) -> TokenStream {
+        // FIXME(jseyfried) quote hygiene
+        quote!(::syntax::ast::Ident::from_str((quote &*self.name.as_str())))
+    }
+}
+
+impl Quote for Symbol {
+    fn quote(&self) -> TokenStream {
+        quote!(::syntax::symbol::Symbol::intern((quote &*self.as_str())))
+    }
+}
+
+impl Quote for Token {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*; $($t:tt)*) => {
+                match *self {
+                    $( Token::$i => quote!(::syntax::parse::token::$i), )*
+                    $( $t )*
+                }
+            }
+        }
+
+        gen_match! {
+            Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
+            Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
+            Underscore;
+
+            Token::OpenDelim(delim) => quote!(::syntax::parse::token::OpenDelim((quote delim))),
+            Token::CloseDelim(delim) => quote!(::syntax::parse::token::CloseDelim((quote delim))),
+            Token::BinOp(tok) => quote!(::syntax::parse::token::BinOp((quote tok))),
+            Token::BinOpEq(tok) => quote!(::syntax::parse::token::BinOpEq((quote tok))),
+            Token::Ident(ident) => quote!(::syntax::parse::token::Ident((quote ident))),
+            Token::Lifetime(ident) => quote!(::syntax::parse::token::Lifetime((quote ident))),
+            Token::Literal(lit, sfx) => quote! {
+                ::syntax::parse::token::Literal((quote lit), (quote sfx))
+            },
+            _ => panic!("Unhandled case!"),
+        }
+    }
+}
+
+impl Quote for token::BinOpToken {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $( token::BinOpToken::$i => quote!(::syntax::parse::token::BinOpToken::$i), )*
+                }
+            }
+        }
+
+        gen_match!(Plus, Minus, Star, Slash, Percent, Caret, And, Or, Shl, Shr)
+    }
+}
+
+impl Quote for Lit {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $( Lit::$i(lit) => quote!(::syntax::parse::token::Lit::$i((quote lit))), )*
+                    _ => panic!("Unsupported literal"),
+                }
+            }
+        }
+
+        gen_match!(Byte, Char, Float, Str_, Integer, ByteStr)
+    }
+}
+
+impl Quote for token::DelimToken {
+    fn quote(&self) -> TokenStream {
+        macro_rules! gen_match {
+            ($($i:ident),*) => {
+                match *self {
+                    $(token::DelimToken::$i => { quote!(::syntax::parse::token::DelimToken::$i) })*
+                }
+            }
+        }
+
+        gen_match!(Paren, Bracket, Brace, NoDelim)
+    }
+}
index 2da442a1a53da752fe2ed2bdffd413599afe91dd..8ce45f3fd08b6b057b0775e34c2213a10be652fa 100644 (file)
@@ -162,6 +162,12 @@ fn from(tt: TokenTree) -> TokenStream {
     }
 }
 
+impl From<Token> for TokenStream {
+    fn from(token: Token) -> TokenStream {
+        TokenTree::Token(DUMMY_SP, token).into()
+    }
+}
+
 impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
         TokenStream::concat(iter.into_iter().map(Into::into).collect::<Vec<_>>())
index 2f94a440e72da3ca5342883acb0d1660ce27e28c..0433b95865ef8c4591479fb9a660d93fd8b38ce2 100644 (file)
@@ -49,9 +49,10 @@ fn cond(input: TokenStream) -> TokenStream {
             _ => false,
         };
         conds.push(if is_else || input.peek().is_none() {
-            qquote!({ unquote rhs })
+            quote!({ $rhs })
         } else {
-            qquote!(if unquote(test.unwrap()) { unquote rhs } else)
+            let test = test.unwrap();
+            quote!(if $test { $rhs } else)
         });
     }
 
index 91075276a302039d221fc5d648de642231f245a4..9522592a5e9e6642d79c072bf873c78e78770682 100644 (file)
@@ -29,6 +29,11 @@ pub fn plugin_registrar(reg: &mut Registry) {
 
 // This macro is not very interesting, but it does contain delimited tokens with
 // no content - `()` and `{}` - which has caused problems in the past.
+// Also, it tests that we can escape `$` via `$$`.
 fn hello(_: TokenStream) -> TokenStream {
-    qquote!({ fn hello() {} hello(); })
+    quote!({
+        fn hello() {}
+        macro_rules! m { ($$($$t:tt)*) => { $$($$t)* } }
+        m!(hello());
+    })
 }
index 612c199e8281a1a02909481ad31620aa979619fb..0e37a7a5dcce22f8daf5d603513812ac44c0689b 100644 (file)
@@ -34,21 +34,21 @@ pub fn plugin_registrar(reg: &mut Registry) {
 }
 
 fn attr_tru(_attr: TokenStream, _item: TokenStream) -> TokenStream {
-    qquote!(fn f1() -> bool { true })
+    quote!(fn f1() -> bool { true })
 }
 
 fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream {
-    qquote!(unquote item)
+    quote!($item)
 }
 
 fn tru(_ts: TokenStream) -> TokenStream {
-    qquote!(true)
+    quote!(true)
 }
 
 fn ret_tru(_ts: TokenStream) -> TokenStream {
-    qquote!(return true;)
+    quote!(return true;)
 }
 
 fn identity(ts: TokenStream) -> TokenStream {
-    qquote!(unquote ts)
+    quote!($ts)
 }
index 57b6c3f0adb89723c77851cee84ada3b7378a426..01b0ed802354c74e19f15f217738caa7bf50a685 100644 (file)
@@ -22,6 +22,6 @@
 use syntax::tokenstream::TokenTree;
 
 fn main() {
-    let true_tok = TokenTree::Token(syntax_pos::DUMMY_SP, token::Ident(Ident::from_str("true")));
-    assert!(qquote!(true).eq_unspanned(&true_tok.into()));
+    let true_tok = token::Ident(Ident::from_str("true"));
+    assert!(quote!(true).eq_unspanned(&true_tok.into()));
 }
diff --git a/src/test/run-pass-fulldeps/macro-quote-empty-delims.rs b/src/test/run-pass-fulldeps/macro-quote-empty-delims.rs
deleted file mode 100644 (file)
index bdbea8a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2012-2014 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that a macro can emit delimiters with nothing inside - `()`, `{}`
-
-// aux-build:hello_macro.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![feature(rustc_private)]
-#![plugin(hello_macro)]
-
-fn main() {
-    hello!();
-}
diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs
new file mode 100644 (file)
index 0000000..bdbea8a
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2012-2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that a macro can emit delimiters with nothing inside - `()`, `{}`
+
+// aux-build:hello_macro.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![feature(rustc_private)]
+#![plugin(hello_macro)]
+
+fn main() {
+    hello!();
+}