Avoid needless reexpansions.
This commit is contained in:
parent
f81f4964d2
commit
50f94f6c95
2 changed files with 18 additions and 16 deletions
|
|
@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*;
|
|||
use ast;
|
||||
use ast::{Name, PatKind};
|
||||
use attr::HasAttrs;
|
||||
use codemap::{self, CodeMap, ExpnInfo};
|
||||
use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
|
||||
use syntax_pos::{Span, ExpnId, NO_EXPANSION};
|
||||
use errors::DiagnosticBuilder;
|
||||
use ext;
|
||||
|
|
@ -805,8 +805,8 @@ impl<'a> ExtCtxt<'a> {
|
|||
/// Extract a string literal from the macro expanded version of `expr`,
|
||||
/// emitting `err_msg` if `expr` is not a string literal. This does not stop
|
||||
/// compilation on error, merely emits a non-fatal error and returns None.
|
||||
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
||||
-> Option<(InternedString, ast::StrStyle)> {
|
||||
pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
||||
-> Option<Spanned<(InternedString, ast::StrStyle)>> {
|
||||
// Update `expr.span`'s expn_id now in case expr is an `include!` macro invocation.
|
||||
let expr = expr.map(|mut expr| {
|
||||
expr.span.expn_id = cx.backtrace;
|
||||
|
|
@ -817,7 +817,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
|||
let expr = cx.expander().fold_expr(expr);
|
||||
match expr.node {
|
||||
ast::ExprKind::Lit(ref l) => match l.node {
|
||||
ast::LitKind::Str(ref s, style) => return Some(((*s).clone(), style)),
|
||||
ast::LitKind::Str(ref s, style) => return Some(respan(expr.span, (s.clone(), style))),
|
||||
_ => cx.span_err(l.span, err_msg)
|
||||
},
|
||||
_ => cx.span_err(expr.span, err_msg)
|
||||
|
|
@ -825,6 +825,11 @@ pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
|||
None
|
||||
}
|
||||
|
||||
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
|
||||
-> Option<(InternedString, ast::StrStyle)> {
|
||||
expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node)
|
||||
}
|
||||
|
||||
/// Non-fatally assert that `tts` is empty. Note that this function
|
||||
/// returns even when `tts` is non-empty, macros that *need* to stop
|
||||
/// compilation should call
|
||||
|
|
@ -851,7 +856,7 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
|
|||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
||||
return None
|
||||
}
|
||||
let ret = cx.expander().fold_expr(panictry!(p.parse_expr()));
|
||||
let ret = panictry!(p.parse_expr());
|
||||
if p.token != token::Eof {
|
||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ use syntax::ast;
|
|||
use syntax::ext::base::*;
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::fold::Folder;
|
||||
use syntax::parse::token::{self, keywords};
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
|
@ -702,10 +701,12 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
||||
let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
|
||||
let macsp = ecx.call_site();
|
||||
// Expand the format literal so that efmt.span will have a backtrace. This
|
||||
// is essential for locating a bug when the format literal is generated in
|
||||
// a macro. (e.g. println!("{}"), which uses concat!($fmt, "\n")).
|
||||
let efmt = ecx.expander().fold_expr(efmt);
|
||||
let msg = "format argument must be a string literal.";
|
||||
let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||
Some(fmt) => fmt,
|
||||
None => return DummyResult::raw_expr(sp),
|
||||
};
|
||||
|
||||
let mut cx = Context {
|
||||
ecx: ecx,
|
||||
args: args,
|
||||
|
|
@ -723,14 +724,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
|
|||
str_pieces: Vec::new(),
|
||||
all_pieces_simple: true,
|
||||
macsp: macsp,
|
||||
fmtsp: efmt.span,
|
||||
};
|
||||
let fmt = match expr_to_string(cx.ecx, efmt, "format argument must be a string literal.") {
|
||||
Some((fmt, _)) => fmt,
|
||||
None => return DummyResult::raw_expr(sp),
|
||||
fmtsp: fmt.span,
|
||||
};
|
||||
|
||||
let mut parser = parse::Parser::new(&fmt);
|
||||
let mut parser = parse::Parser::new(&fmt.node.0);
|
||||
let mut pieces = vec![];
|
||||
|
||||
loop {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue