Change:
With landed, the lifetime of is now problematic. Specifically, the following used to work and now fails: The lifetime of is now limited to that branch of the match, so it doesn't live long enough to be assigned to . I'm not sure if this means lifetimes need to change. The other option is that needs to return a . Unfortunately, the only way to do that right now is to make it equivalent to , which makes it no longer usable as the value of a constant (e.g. ). I'm thinking the right solution is to make it legal for me to say . I can type that right now, but the lifetime seems to be wholly ignored, as I get the exact same error with the following as I do with the example above: If becomes a valid expression with the lifetime, then could start evaluating to that and everything should work as expected. Furthermore, it would be nice (but perhaps not required) if , where all elements are compile-time constants, would implicitly be given the lifetime.
/cc
Yeah, this is kind of annoying. I worked around it in one specific case by having bytes! expand as follows: I certainly think one should be allowed to write a concrete lifetime as part of a slice or borrow expression, and ought to be legal -- we'll obviously have to impose more stringent constant-related rules. In the short term, we could adjust to expand in the pattern I showed above. What was unclear to me was whether this is sufficient workaround, or whether we'll want something more general. Interestingly, even if we used full inference, the expression you gave above would be illegal unless we introduce a special case for static byte strings, because it generates a conditional temporary (only on one arm of the match) and we can't handle the cleanup for such a case without zeroing, which we plan to remove (well, I guess we could also have a special case for temporary types [like ) that do not require drop glue, but I'd rather not).
Perhaps the simplest fix for now is to adjust the macro itself to expand to a static item as I showed. I should probably have done that more generally but I was ready to land that expletive branch already.
Won't that prevent from being able to expand to a static?
I already adjusted like that and is correct, it prevents , which is definitely already used in our codebase.
Ah, unfortunate. (I actually think we should allow statics to include nested blocks with other statics, but I guess that's a separate bug) Well, I'm not sure what's the easiest fix in that case, I guess just to fix the semantics of so that it guarantees static data. I'm not 100% sure what's implied by such a fix: it doesn't seem too hard ;)
cc

Discussion:
Some(e) => e, }; let mut bytes = Vec::new(); <ins> let mut err = false; </ins> for expr in exprs.iter() { match expr.node {

// u8 literal, push to vector expression ast::LitUint(v, ast::TyU8) => { if v > 0xFF { <del> cx.span_err(expr.span, "too large u8 literal in bytes!") </del> <ins> cx.span_err(expr.span, "too large u8 literal in bytes!"); err = true; </ins> } else { bytes.push(cx.expr_u8(expr.span, v as u8)); }

// integer literal, push to vector expression ast::LitIntUnsuffixed(v) => { if v > 0xFF { <del> cx.span_err(expr.span, "too large integer literal in bytes!") </del> <ins> cx.span_err(expr.span, "too large integer literal in bytes!"); err = true; </ins> } else if v < 0 { <del> cx.span_err(expr.span, "negative integer literal in bytes!") </del> <ins> cx.span_err(expr.span, "negative integer literal in bytes!"); err = true; </ins> } else { bytes.push(cx.expr_u8(expr.span, v as u8)); }

if v.is_ascii() { bytes.push(cx.expr_u8(expr.span, v as u8)); } else { <del> cx.span_err(expr.span, "non-ascii char literal in bytes!") </del> <ins> cx.span_err(expr.span, "non-ascii char literal in bytes!"); err = true; </ins> } } <del> _ => cx.span_err(expr.span, "unsupported literal in bytes!") </del> <ins> _ => { cx.span_err(expr.span, "unsupported literal in bytes!"); err = true; } </ins> }, <del> _ => cx.span_err(expr.span, "non-literal in bytes!") </del> <ins> _ => { cx.span_err(expr.span, "non-literal in bytes!"); err = true; } </ins> } } <ins> // 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); } </ins> let e = cx.expr_vec_slice(sp, bytes); <ins> let e = quote_expr!(cx, { static BYTES: &'static [u8] = $e; BYTES}); </ins> MacExpr::new(e) }

<ins> // 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()); } </ins>