Skip to content

Commit

Permalink
proc_macro: don't try to reflect literals in quasi-quoting.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jul 19, 2018
1 parent c0adb05 commit d10d0b3
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 95 deletions.
2 changes: 1 addition & 1 deletion src/libproc_macro/lib.rs
Expand Up @@ -1364,7 +1364,7 @@ impl TokenTree {
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[doc(hidden)]
pub mod __internal {
pub use quote::{LiteralKind, SpannedSymbol, Quoter, unquote};
pub use quote::{Quoter, unquote};

use std::cell::Cell;
use std::ptr;
Expand Down
109 changes: 15 additions & 94 deletions src/libproc_macro/quote.rs
Expand Up @@ -17,8 +17,6 @@
use {Delimiter, Literal, Spacing, Span, Ident, Punct, Group, TokenStream, TokenTree};

use syntax::ext::base::{ExtCtxt, ProcMacro};
use syntax::parse::token;
use syntax::symbol::Symbol;
use syntax::tokenstream;

/// This is the actual quote!() proc macro
Expand All @@ -42,6 +40,7 @@ macro_rules! quote_tok {
(,) => { tt2ts!(Punct::new(',', Spacing::Alone)) };
(.) => { tt2ts!(Punct::new('.', Spacing::Alone)) };
(:) => { tt2ts!(Punct::new(':', Spacing::Alone)) };
(;) => { tt2ts!(Punct::new(';', Spacing::Alone)) };
(|) => { tt2ts!(Punct::new('|', Spacing::Alone)) };
(::) => {
[
Expand All @@ -61,6 +60,7 @@ macro_rules! quote_tok {
(_) => { tt2ts!(Punct::new('_', Spacing::Alone)) };
(0) => { tt2ts!(Literal::i8_unsuffixed(0)) };
(&) => { tt2ts!(Punct::new('&', Spacing::Alone)) };
(=) => { tt2ts!(Punct::new('=', Spacing::Alone)) };
($i:ident) => { tt2ts!(Ident::new(stringify!($i), Span::def_site())) };
}

Expand Down Expand Up @@ -92,15 +92,6 @@ impl ProcMacro for Quoter {
}
}

impl<T: Quote> Quote for Option<T> {
fn quote(self) -> TokenStream {
match self {
Some(t) => quote!(Some((quote t))),
None => quote!(None),
}
}
}

impl Quote for TokenStream {
fn quote(self) -> TokenStream {
if self.is_empty() {
Expand Down Expand Up @@ -194,93 +185,23 @@ impl Quote for Span {
}
}

macro_rules! literals {
($($i:ident),*; $($raw:ident),*) => {
pub struct SpannedSymbol {
sym: Symbol,
span: Span,
}

impl SpannedSymbol {
pub fn new(string: &str, span: Span) -> SpannedSymbol {
SpannedSymbol { sym: Symbol::intern(string), span }
}
}

impl Quote for SpannedSymbol {
fn quote(self) -> TokenStream {
quote!(::__internal::SpannedSymbol::new((quote self.sym.as_str()),
(quote self.span)))
}
}

pub enum LiteralKind {
$($i,)*
$($raw(u16),)*
}

impl LiteralKind {
pub fn with_contents_and_suffix(self, contents: SpannedSymbol,
suffix: Option<SpannedSymbol>) -> Literal {
let sym = contents.sym;
let suffix = suffix.map(|t| t.sym);
match self {
$(LiteralKind::$i => {
Literal {
lit: token::Lit::$i(sym),
suffix,
span: contents.span,
}
})*
$(LiteralKind::$raw(n) => {
Literal {
lit: token::Lit::$raw(sym, n),
suffix,
span: contents.span,
}
})*
}
}
}

impl Literal {
fn kind_contents_and_suffix(self) -> (LiteralKind, SpannedSymbol, Option<SpannedSymbol>)
{
let (kind, contents) = match self.lit {
$(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
$(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
};
let suffix = self.suffix.map(|sym| SpannedSymbol::new(&sym.as_str(), self.span()));
(kind, SpannedSymbol::new(&contents.as_str(), self.span()), suffix)
}
}

impl Quote for LiteralKind {
fn quote(self) -> TokenStream {
match self {
$(LiteralKind::$i => quote! {
::__internal::LiteralKind::$i
},)*
$(LiteralKind::$raw(n) => quote! {
::__internal::LiteralKind::$raw((quote n))
},)*
}
}
}

impl Quote for Literal {
fn quote(self) -> TokenStream {
let (kind, contents, suffix) = self.kind_contents_and_suffix();
quote! {
(quote kind).with_contents_and_suffix((quote contents), (quote suffix))
}
impl Quote for Literal {
fn quote(self) -> TokenStream {
quote! {{
let mut iter = (quote self.to_string())
.parse::<::TokenStream>()
.unwrap()
.into_iter();
if let (Some(::TokenTree::Literal(mut lit)), None) = (iter.next(), iter.next()) {
lit.set_span((quote self.span));
lit
} else {
unreachable!()
}
}
}}
}
}

literals!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw);

impl Quote for Delimiter {
fn quote(self) -> TokenStream {
macro_rules! gen_match {
Expand Down

0 comments on commit d10d0b3

Please sign in to comment.