]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #12370 : rcxdude/rust/macro_fix, r=alexcrichton
authorbors <bors@rust-lang.org>
Wed, 19 Feb 2014 12:41:45 +0000 (04:41 -0800)
committerbors <bors@rust-lang.org>
Wed, 19 Feb 2014 12:41:45 +0000 (04:41 -0800)
Closes #11692. Instead of returning the original expression, a dummy expression
(with identical span) is returned. This prevents infinite loops of failed
expansions as well as odd double error messages in certain situations.

This is a slightly better fix than #12197, because it does not produce a double error and also fixes a few other cases where an infinite loop could happen.

This does not fix the other issue in #11692 (non-builtin macros not being recognised when expanded inside macros), which I think should be moved into a separate issue.

src/libsyntax/ext/asm.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/bytes.rs
src/libsyntax/ext/concat.rs
src/libsyntax/ext/concat_idents.rs
src/libsyntax/ext/env.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/trace_macros.rs
src/test/compile-fail/issue-11692.rs [new file with mode: 0644]

index 1a3ebf3ce5d1cccdbd04140d1ec338f59cebcc02..1bf82573c494909b7b2b8455b327f703d65ca791 100644 (file)
@@ -64,7 +64,7 @@ pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                                    "inline assembly must be a string literal.") {
                     Some((s, st)) => (s, st),
                     // let compilation continue
-                    None => return MacResult::dummy_expr(),
+                    None => return MacResult::dummy_expr(sp),
                 };
                 asm = s;
                 asm_str_style = Some(style);
index 3dac82ae3b77f5e6ef0b57ebad59dde4cfbac2b4..e6fffe8b53f4817c11992b72d635f64c935da510 100644 (file)
@@ -101,6 +101,7 @@ pub trait AnyMacro {
     fn make_stmt(&self) -> @ast::Stmt;
 }
 
+
 pub enum MacResult {
     MRExpr(@ast::Expr),
     MRItem(@ast::Item),
@@ -112,10 +113,15 @@ impl MacResult {
     /// type signatures after emitting a non-fatal error (which stop
     /// compilation well before the validity (or otherwise)) of the
     /// expression are checked.
-    pub fn dummy_expr() -> MacResult {
-        MRExpr(@ast::Expr {
-                id: ast::DUMMY_NODE_ID, node: ast::ExprLogLevel, span: codemap::DUMMY_SP
-            })
+    pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
+        @ast::Expr {
+            id: ast::DUMMY_NODE_ID,
+            node: ast::ExprLogLevel,
+            span: sp
+        }
+    }
+    pub fn dummy_expr(sp: codemap::Span) -> MacResult {
+        MRExpr(MacResult::raw_dummy_expr(sp))
     }
 }
 
index 39bb870b969a0798489aa86390c1101a0d5432fd..68aa757c524fb3f9b32aecc12e36938fafa9188f 100644 (file)
@@ -21,7 +21,7 @@
 pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult {
     // Gather all argument expressions
     let exprs = match get_exprs_from_tts(cx, sp, tts) {
-        None => return MacResult::dummy_expr(),
+        None => return MacResult::dummy_expr(sp),
         Some(e) => e,
     };
     let mut bytes = ~[];
index c13f9bf92af022257248a152aa18b7ee090b5216..5316b8f721248d3a10613360cc477ade984edf97 100644 (file)
@@ -21,7 +21,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                          tts: &[ast::TokenTree]) -> base::MacResult {
     let es = match base::get_exprs_from_tts(cx, sp, tts) {
         Some(e) => e,
-        None => return base::MacResult::dummy_expr()
+        None => return base::MacResult::dummy_expr(sp)
     };
     let mut accumulator = ~"";
     for e in es.move_iter() {
index 15e9d31daa00fc24c4841f131f6364647fe56356..85cfd4f61e414fc6f53a7ec23343d9c7769f32da 100644 (file)
@@ -25,7 +25,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 ast::TTTok(_, token::COMMA) => (),
                 _ => {
                     cx.span_err(sp, "concat_idents! expecting comma.");
-                    return MacResult::dummy_expr();
+                    return MacResult::dummy_expr(sp);
                 }
             }
         } else {
@@ -35,7 +35,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 }
                 _ => {
                     cx.span_err(sp, "concat_idents! requires ident args.");
-                    return MacResult::dummy_expr();
+                    return MacResult::dummy_expr(sp);
                 }
             }
         }
index c23a1ce1e28d5f8592ec559bec8a12323cf1b7bb..fec1e70af0735719cc8a8dcf8ac9acd9186229de 100644 (file)
@@ -26,7 +26,7 @@
 pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     -> base::MacResult {
     let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
-        None => return MacResult::dummy_expr(),
+        None => return MacResult::dummy_expr(sp),
         Some(v) => v
     };
 
@@ -42,14 +42,14 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     let exprs = match get_exprs_from_tts(cx, sp, tts) {
         Some([]) => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
-            return MacResult::dummy_expr();
+            return MacResult::dummy_expr(sp);
         }
-        None => return MacResult::dummy_expr(),
+        None => return MacResult::dummy_expr(sp),
         Some(exprs) => exprs
     };
 
     let var = match expr_to_str(cx, exprs[0], "expected string literal") {
-        None => return MacResult::dummy_expr(),
+        None => return MacResult::dummy_expr(sp),
         Some((v, _style)) => v
     };
     let msg = match exprs.len() {
@@ -60,13 +60,13 @@ pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
         }
         2 => {
             match expr_to_str(cx, exprs[1], "expected string literal") {
-                None => return MacResult::dummy_expr(),
+                None => return MacResult::dummy_expr(sp),
                 Some((s, _style)) => s
             }
         }
         _ => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
-            return MacResult::dummy_expr();
+            return MacResult::dummy_expr(sp);
         }
     };
 
index 97766e1a14b487fae56da4fa7b40bad6c3a9a9a2..4b81713f7d0c9a4b4cb22b97ab5b579d63894689 100644 (file)
@@ -51,7 +51,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                             format!("expected macro name without module \
                                   separators"));
                         // let compilation continue
-                        return e;
+                        return MacResult::raw_dummy_expr(e.span);
                     }
                     let extname = pth.segments[0].identifier;
                     let extnamestr = token::get_ident(extname);
@@ -64,7 +64,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                                         extnamestr.get()));
 
                             // let compilation continue
-                            return e;
+                            return MacResult::raw_dummy_expr(e.span);
                         }
                         Some(&NormalTT(ref expandfun, exp_span)) => {
                             fld.cx.bt_push(ExpnInfo {
@@ -98,7 +98,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                                             extnamestr.get()
                                         )
                                     );
-                                    return e;
+                                    return MacResult::raw_dummy_expr(e.span);
                                 }
                             };
 
@@ -111,7 +111,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                                 format!("'{}' is not a tt-style macro",
                                         extnamestr.get())
                             );
-                            return e;
+                            return MacResult::raw_dummy_expr(e.span);
                         }
                     };
 
index 01d348595b88c08d993c0b1804f048e364a8defd..13b1afb4c007c8cb2cfc9fa6c4bc1021a22c00ad 100644 (file)
@@ -811,7 +811,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
                                 expr,
                                 "format argument must be a string literal.") {
         Some((fmt, _)) => fmt,
-        None => return efmt
+        None => return MacResult::raw_dummy_expr(sp)
     };
 
     let mut parser = parse::Parser::new(fmt.get());
@@ -829,7 +829,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
     match parser.errors.shift() {
         Some(error) => {
             cx.ecx.span_err(efmt.span, "invalid format string: " + error);
-            return efmt;
+            return MacResult::raw_dummy_expr(sp);
         }
         None => {}
     }
index 150f054b2afe4f43bf97bccab4c7c12189ff3101..c81ee55c23768aa75d1ec0eaf8a5f27432ee17fc 100644 (file)
@@ -83,7 +83,7 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     -> base::MacResult {
     let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
         Some(f) => f,
-        None => return MacResult::dummy_expr(),
+        None => return MacResult::dummy_expr(sp),
     };
     // The file will be added to the code map by the parser
     let mut p =
@@ -101,13 +101,13 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     -> base::MacResult {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
         Some(f) => f,
-        None => return MacResult::dummy_expr()
+        None => return MacResult::dummy_expr(sp)
     };
     let file = res_rel_file(cx, sp, &Path::new(file));
     let bytes = match File::open(&file).read_to_end() {
         Err(e) => {
             cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
-            return MacResult::dummy_expr();
+            return MacResult::dummy_expr(sp);
         }
         Ok(bytes) => bytes,
     };
@@ -123,7 +123,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
         }
         None => {
             cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
-            return MacResult::dummy_expr();
+            return MacResult::dummy_expr(sp);
         }
     }
 }
@@ -133,13 +133,13 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
         Some(f) => f,
-        None => return MacResult::dummy_expr()
+        None => return MacResult::dummy_expr(sp)
     };
     let file = res_rel_file(cx, sp, &Path::new(file));
     match File::open(&file).read_to_end() {
         Err(e) => {
             cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
-            return MacResult::dummy_expr();
+            return MacResult::dummy_expr(sp);
         }
         Ok(bytes) => {
             base::MRExpr(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
index 4189ea6a967a82ec1c653b34236499425996cb0e..db2c9dcddb6dcdee3c439dc839c082a5d0ccc60f 100644 (file)
@@ -33,7 +33,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
         cx.set_trace_macros(false);
     } else {
         cx.span_err(sp, "trace_macros! only accepts `true` or `false`");
-        return base::MacResult::dummy_expr();
+        return base::MacResult::dummy_expr(sp);
     }
 
     rust_parser.bump();
diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692.rs
new file mode 100644 (file)
index 0000000..aed2c4d
--- /dev/null
@@ -0,0 +1,19 @@
+// 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 <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.
+
+fn main() {
+    print!(test!());
+    //~^ ERROR: macro undefined: 'test'
+    //~^^ ERROR: format argument must be a string literal
+
+    concat!(test!());
+    //~^ ERROR: macro undefined: 'test'
+    //~^^ ERROR: expected a literal
+}