Closed
Description
here is a snippet of code (i've pasted the full example at the bottom):
fn main() {
let e = quote_expr!((), x + y);
println!("expr: {:s}", e.to_str());
let p = quote_pat!((), x + y);
println!("pat: {:s}", p.to_str());
}
Once #12264 is fixed, then you can compile and run this, and you'll get:
% ./cfg
expr: x + y
pat: x
In particular, I fed x + y
into both quote_expr!
and into quote_pat!
, and the + y
was simply silently discarded when quote_pat!
parsed its input.
The macros should check for trailing input and issue a warning (that one could then use allow/deny/forbid on).
Here is the full example code (again, won't compile until #12264 is fixed):
#[feature(managed_boxes)];
#[feature(quote)];
#[feature(macro_rules)];
extern mod syntax;
extern mod rustc;
use syntax::ast;
use syntax::codemap;
use syntax::parse;
use syntax::parse::token;
use syntax::print::pprust;
fn main() {
let e = quote_expr!((), x + y);
println!("expr: {:s}", e.to_str());
let p = quote_pat!((), x + y);
println!("pat: {:s}", p.to_str());
}
trait SyntaxToStr {
fn get_interner(&self) -> @token::IdentInterner { token::get_ident_interner() }
fn get_to_str() -> fn (_: &Self, intr: @token::IdentInterner) -> ~str;
fn to_str(&self) -> ~str { SyntaxToStr::get_to_str()(self, self.get_interner()) }
}
macro_rules! impl_stx_to_str {
($Type:path, $func:path) => {
impl SyntaxToStr for $Type {
fn get_to_str() -> fn (_: &$Type, intr: @token::IdentInterner) -> ~str {
$func
}
}
}
}
impl_stx_to_str!(ast::Ty, pprust::ty_to_str)
impl_stx_to_str!(ast::Pat, pprust::pat_to_str)
impl_stx_to_str!(ast::Expr, pprust::expr_to_str)
impl_stx_to_str!(ast::Stmt, pprust::stmt_to_str)
impl_stx_to_str!(ast::Item, pprust::item_to_str)
impl_stx_to_str!(ast::Generics, pprust::generics_to_str)
impl_stx_to_str!(ast::Path, pprust::path_to_str)
trait QuoteCtxt {
fn parse_sess(&self) -> @syntax::parse::ParseSess;
fn cfg(&self) -> ast::CrateConfig;
fn call_site(&self) -> codemap::Span;
fn ident_of(&self, st: &str) -> ast::Ident;
}
impl QuoteCtxt for () {
fn parse_sess(&self) -> @syntax::parse::ParseSess { parse::new_parse_sess() }
fn cfg(&self) -> ast::CrateConfig { ~[] }
fn call_site(&self) -> codemap::Span { codemap::DUMMY_SP }
fn ident_of(&self, st: &str) -> ast::Ident { token::str_to_ident(st) }
}