about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libsyntax/ext/bytes.rs33
-rw-r--r--src/test/run-pass/bytes-macro-static.rs21
2 files changed, 48 insertions, 6 deletions
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index 06b50e37cbd..b2088d2bc82 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -25,6 +25,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
         Some(e) => e,
     };
     let mut bytes = Vec::new();
+    let mut err = false;
 
     for expr in exprs.iter() {
         match expr.node {
@@ -40,7 +41,8 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 // u8 literal, push to vector expression
                 ast::LitUint(v, ast::TyU8) => {
                     if v > 0xFF {
-                        cx.span_err(expr.span, "too large u8 literal in bytes!")
+                        cx.span_err(expr.span, "too large u8 literal in bytes!");
+                        err = true;
                     } else {
                         bytes.push(cx.expr_u8(expr.span, v as u8));
                     }
@@ -49,9 +51,11 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 // integer literal, push to vector expression
                 ast::LitIntUnsuffixed(v) => {
                     if v > 0xFF {
-                        cx.span_err(expr.span, "too large integer literal in bytes!")
+                        cx.span_err(expr.span, "too large integer literal in bytes!");
+                        err = true;
                     } else if v < 0 {
-                        cx.span_err(expr.span, "negative integer literal in bytes!")
+                        cx.span_err(expr.span, "negative integer literal in bytes!");
+                        err = true;
                     } else {
                         bytes.push(cx.expr_u8(expr.span, v as u8));
                     }
@@ -62,17 +66,34 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                     if v.is_ascii() {
                         bytes.push(cx.expr_u8(expr.span, v as u8));
                     } else {
-                        cx.span_err(expr.span, "non-ascii char literal in bytes!")
+                        cx.span_err(expr.span, "non-ascii char literal in bytes!");
+                        err = true;
                     }
                 }
 
-                _ => cx.span_err(expr.span, "unsupported literal in bytes!")
+                _ => {
+                    cx.span_err(expr.span, "unsupported literal in bytes!");
+                    err = true;
+                }
             },
 
-            _ => cx.span_err(expr.span, "non-literal in bytes!")
+            _ => {
+                cx.span_err(expr.span, "non-literal in bytes!");
+                err = true;
+            }
         }
     }
 
+    // For some reason using quote_expr!() here aborts if we threw an error.
+    // I'm assuming that the end of the recursive parse tricks the compiler
+    // into thinking this is a good time to stop. But we'd rather keep going.
+    if err {
+        // Since the compiler will stop after the macro expansion phase anyway, we
+        // don't need type info, so we can just return a DummyResult
+        return DummyResult::expr(sp);
+    }
+
     let e = cx.expr_vec_slice(sp, bytes);
+    let e = quote_expr!(cx, { static BYTES: &'static [u8] = $e; BYTES});
     MacExpr::new(e)
 }
diff --git a/src/test/run-pass/bytes-macro-static.rs b/src/test/run-pass/bytes-macro-static.rs
new file mode 100644
index 00000000000..7f4bbda8e30
--- /dev/null
+++ b/src/test/run-pass/bytes-macro-static.rs
@@ -0,0 +1,21 @@
+// 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.
+
+static FOO: &'static [u8] = bytes!("hello, world");
+
+pub fn main() {
+    let b = match true {
+        true => bytes!("test"),
+        false => unreachable!()
+    };
+
+    assert_eq!(b, "test".as_bytes());
+    assert_eq!(FOO, "hello, world".as_bytes());
+}