diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e9fe21eded60..5cb09ec82322 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -405,11 +405,13 @@ impl<'a> ExtCtxt<'a> { } } -/// Extract a string literal from `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_str(cx: &ExtCtxt, expr: @ast::Expr, err_msg: &str) +/// 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_str(cx: &mut ExtCtxt, expr: @ast::Expr, err_msg: &str) -> Option<(InternedString, ast::StrStyle)> { + // we want to be able to handle e.g. concat("foo", "bar") + let expr = cx.expand_expr(expr); match expr.node { ast::ExprLit(l) => match l.node { ast::LitStr(ref s, style) => return Some(((*s).clone(), style)), @@ -457,7 +459,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt, /// Extract comma-separated expressions from `tts`. If there is a /// parsing error, emit a non-fatal error and return None. -pub fn get_exprs_from_tts(cx: &ExtCtxt, +pub fn get_exprs_from_tts(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Option > { let mut p = parse::new_parser_from_tts(cx.parse_sess(), @@ -471,7 +473,7 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt, cx.span_err(sp, "expected token: `,`"); return None; } - es.push(p.parse_expr()); + es.push(cx.expand_expr(p.parse_expr())); } Some(es) } @@ -482,9 +484,6 @@ pub fn get_exprs_from_tts(cx: &ExtCtxt, // This environment maps Names to SyntaxExtensions. -// Actually, the following implementation is parameterized -// by both key and value types. - //impl question: how to implement it? Initially, the // env will contain only macros, so it might be painful // to add an empty frame for every context. Let's just @@ -500,14 +499,6 @@ struct MapChainFrame { map: HashMap, } -#[unsafe_destructor] -impl Drop for MapChainFrame { - fn drop(&mut self) { - // make sure that syntax extension dtors run before we drop the libs - self.map.clear(); - } -} - // Only generic to make it easy to test pub struct SyntaxEnv { priv chain: Vec , diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index 5316b8f72124..e638291ecfa3 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -25,7 +25,6 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, }; let mut accumulator = ~""; for e in es.move_iter() { - let e = cx.expand_expr(e); match e.node { ast::ExprLit(lit) => { match lit.node { diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 7752d8859682..b27ea3df21ec 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -843,11 +843,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, fmtsp: sp, }; cx.fmtsp = efmt.span; - // Be sure to recursively expand macros just in case the format string uses - // a macro to build the format expression. - let expr = cx.ecx.expand_expr(efmt); let fmt = match expr_to_str(cx.ecx, - expr, + efmt, "format argument must be a string literal.") { Some((fmt, _)) => fmt, None => return MacResult::raw_dummy_expr(sp) diff --git a/src/test/run-pass/phase-syntax-link-does-resolve.rs b/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs similarity index 100% rename from src/test/run-pass/phase-syntax-link-does-resolve.rs rename to src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs diff --git a/src/test/run-pass/asm-concat-src.rs b/src/test/run-pass/asm-concat-src.rs new file mode 100644 index 000000000000..96c98a037205 --- /dev/null +++ b/src/test/run-pass/asm-concat-src.rs @@ -0,0 +1,16 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-fast #[feature] doesn't work with check-fast +#[feature(asm)]; + +pub fn main() { + unsafe { asm!(concat!("", "")) }; +} diff --git a/src/test/run-pass/asm-out-assign.rs b/src/test/run-pass/asm-out-assign.rs index 823da4faaf63..2f6b87f26a72 100644 --- a/src/test/run-pass/asm-out-assign.rs +++ b/src/test/run-pass/asm-out-assign.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // diff --git a/src/test/run-pass/ext-expand-inner-exprs.rs b/src/test/run-pass/ext-expand-inner-exprs.rs new file mode 100644 index 000000000000..1c96cbd93142 --- /dev/null +++ b/src/test/run-pass/ext-expand-inner-exprs.rs @@ -0,0 +1,15 @@ +// Copyright 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static FOO : &'static [u8] = bytes!(concat!(concat!("hel", "lo"), "world")); + +pub fn main() { + assert_eq!(FOO, "helloworld".as_bytes()); +}