From 29a63fb0a098485b5d2c561b6f9a7e458d3a6a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 29 Jul 2018 16:38:01 -0700 Subject: [PATCH 1/5] Teach `concat!()` to concatenate byte str literals --- src/libsyntax/ast.rs | 5 +++ src/libsyntax_ext/concat.rs | 62 +++++++++++++++++++++++++++------ src/test/compile-fail/concat.rs | 4 +-- src/test/ui/byte-concat.rs | 15 ++++++++ src/test/ui/byte-concat.stderr | 18 ++++++++++ 5 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/byte-concat.rs create mode 100644 src/test/ui/byte-concat.stderr diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1b6b47f5489d7..44cfd8833336a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1300,6 +1300,11 @@ impl LitKind { } } + /// Returns a `LitKind::ByteStr` from `content`. + pub fn new_byte_str(content: Vec) -> LitKind { + LitKind::ByteStr(Lrc::new(content)) + } + /// Returns true if this is a numeric literal. pub fn is_numeric(&self) -> bool { match *self { diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index dcdd2c590e01f..a5d04b6acc1fa 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -13,20 +13,23 @@ use syntax::ext::base; use syntax::ext::build::AstBuilder; use syntax::symbol::Symbol; use syntax::tokenstream; -use syntax_pos; +use syntax_pos::Span; use std::string::String; pub fn expand_syntax_ext( cx: &mut base::ExtCtxt, - sp: syntax_pos::Span, + sp: Span, tts: &[tokenstream::TokenTree], ) -> Box { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, None => return base::DummyResult::expr(sp), }; - let mut accumulator = String::new(); + let mut string_accumulator = String::new(); + let mut string_pos = vec![]; + let mut b_accumulator: Vec = vec![]; + let mut b_pos: Vec = vec![]; let mut missing_literal = vec![]; for e in es { match e.node { @@ -34,21 +37,30 @@ pub fn expand_syntax_ext( ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) | ast::LitKind::FloatUnsuffixed(ref s) => { - accumulator.push_str(&s.as_str()); + string_accumulator.push_str(&s.as_str()); + string_pos.push(e.span); } ast::LitKind::Char(c) => { - accumulator.push(c); + string_accumulator.push(c); + string_pos.push(e.span); } ast::LitKind::Int(i, ast::LitIntType::Unsigned(_)) | ast::LitKind::Int(i, ast::LitIntType::Signed(_)) | ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => { - accumulator.push_str(&i.to_string()); + string_accumulator.push_str(&i.to_string()); + string_pos.push(e.span); } ast::LitKind::Bool(b) => { - accumulator.push_str(&b.to_string()); + string_accumulator.push_str(&b.to_string()); + string_pos.push(e.span); } - ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..) => { - cx.span_err(e.span, "cannot concatenate a byte string literal"); + ast::LitKind::Byte(byte) => { + b_accumulator.push(byte); + b_pos.push(e.span); + } + ast::LitKind::ByteStr(ref b_str) => { + b_accumulator.extend(b_str.iter()); + b_pos.push(e.span); } }, _ => { @@ -61,6 +73,36 @@ pub fn expand_syntax_ext( err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); } + // Do not allow mixing "" and b"" + if string_accumulator.len() > 0 && b_accumulator.len() > 0 { + let mut err = cx.struct_span_err( + b_pos.clone(), + "cannot concatenate a byte string literal with string literals", + ); + for pos in &b_pos { + err.span_label(*pos, "byte string literal"); + } + for pos in &string_pos { + err.span_label(*pos, "string literal"); + + } + err.help("do not mix byte string literals and string literals"); + err.multipart_suggestion( + "you can use byte string literals", + string_pos + .iter() + .map(|pos| (pos.shrink_to_lo(), "b".to_string())) + .collect(), + ); + err.emit(); + } let sp = sp.apply_mark(cx.current_expansion.mark); - base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) + if b_accumulator.len() > 0 { + base::MacEager::expr(cx.expr_lit( + sp, + ast::LitKind::new_byte_str(b_accumulator), + )) + } else { + base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string_accumulator))) + } } diff --git a/src/test/compile-fail/concat.rs b/src/test/compile-fail/concat.rs index e29c6ac5d5e94..6c4d160138fb6 100644 --- a/src/test/compile-fail/concat.rs +++ b/src/test/compile-fail/concat.rs @@ -9,8 +9,8 @@ // except according to those terms. fn main() { - concat!(b'f'); //~ ERROR: cannot concatenate a byte string literal - concat!(b"foo"); //~ ERROR: cannot concatenate a byte string literal + concat!(b'f'); + concat!(b"foo"); concat!(foo); //~ ERROR: expected a literal concat!(foo()); //~ ERROR: expected a literal } diff --git a/src/test/ui/byte-concat.rs b/src/test/ui/byte-concat.rs new file mode 100644 index 0000000000000..893c949bc3f85 --- /dev/null +++ b/src/test/ui/byte-concat.rs @@ -0,0 +1,15 @@ +// Copyright 2018 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. + +fn main() { + let _ = concat!(b"abc", b"def"); + let _ = concat!("abc", b"def", "ghi", b"jkl"); + //~^ ERROR cannot concatenate a byte string literal with string literals +} diff --git a/src/test/ui/byte-concat.stderr b/src/test/ui/byte-concat.stderr new file mode 100644 index 0000000000000..c065d496cc54a --- /dev/null +++ b/src/test/ui/byte-concat.stderr @@ -0,0 +1,18 @@ +error: cannot concatenate a byte string literal with string literals + --> $DIR/byte-concat.rs:13:28 + | +LL | let _ = concat!("abc", b"def", "ghi", b"jkl"); + | ----- ^^^^^^ ----- ^^^^^^ byte string literal + | | | | + | | | string literal + | | byte string literal + | string literal + | + = help: do not mix byte string literals and string literals +help: you can use byte string literals + | +LL | let _ = concat!(b"abc", b"def", b"ghi", b"jkl"); + | ^ ^ + +error: aborting due to previous error + From 35bdb947abcf1371f24b09264848bfd003d42bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 31 Jul 2018 10:34:39 -0700 Subject: [PATCH 2/5] Move concat test to ui and unify with new test --- src/test/compile-fail/concat.rs | 16 ----------- src/test/ui/byte-concat.stderr | 18 ------------ src/test/ui/{byte-concat.rs => concat.rs} | 13 +++++++-- src/test/ui/concat.stderr | 35 +++++++++++++++++++++++ 4 files changed, 45 insertions(+), 37 deletions(-) delete mode 100644 src/test/compile-fail/concat.rs delete mode 100644 src/test/ui/byte-concat.stderr rename src/test/ui/{byte-concat.rs => concat.rs} (53%) create mode 100644 src/test/ui/concat.stderr diff --git a/src/test/compile-fail/concat.rs b/src/test/compile-fail/concat.rs deleted file mode 100644 index 6c4d160138fb6..0000000000000 --- a/src/test/compile-fail/concat.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 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. - -fn main() { - concat!(b'f'); - concat!(b"foo"); - concat!(foo); //~ ERROR: expected a literal - concat!(foo()); //~ ERROR: expected a literal -} diff --git a/src/test/ui/byte-concat.stderr b/src/test/ui/byte-concat.stderr deleted file mode 100644 index c065d496cc54a..0000000000000 --- a/src/test/ui/byte-concat.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: cannot concatenate a byte string literal with string literals - --> $DIR/byte-concat.rs:13:28 - | -LL | let _ = concat!("abc", b"def", "ghi", b"jkl"); - | ----- ^^^^^^ ----- ^^^^^^ byte string literal - | | | | - | | | string literal - | | byte string literal - | string literal - | - = help: do not mix byte string literals and string literals -help: you can use byte string literals - | -LL | let _ = concat!(b"abc", b"def", b"ghi", b"jkl"); - | ^ ^ - -error: aborting due to previous error - diff --git a/src/test/ui/byte-concat.rs b/src/test/ui/concat.rs similarity index 53% rename from src/test/ui/byte-concat.rs rename to src/test/ui/concat.rs index 893c949bc3f85..9f2ace52df571 100644 --- a/src/test/ui/byte-concat.rs +++ b/src/test/ui/concat.rs @@ -1,4 +1,4 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,7 +9,14 @@ // except according to those terms. fn main() { - let _ = concat!(b"abc", b"def"); - let _ = concat!("abc", b"def", "ghi", b"jkl"); + concat!(b'f'); // b'' concat is supported + concat!(b"foo"); // b"" concat is supported + concat!(foo); + //~^ ERROR: expected a literal + concat!(foo()); + //~^ ERROR: expected a literal + concat!(b'a', b"bc", b"def"); + concat!("abc", b"def", 'g', "hi", b"jkl"); //~^ ERROR cannot concatenate a byte string literal with string literals + // `concat!()` cannot mix "" and b"" literals (it might allow it in the future) } diff --git a/src/test/ui/concat.stderr b/src/test/ui/concat.stderr new file mode 100644 index 0000000000000..f1aa766cd0e5d --- /dev/null +++ b/src/test/ui/concat.stderr @@ -0,0 +1,35 @@ +error: expected a literal + --> $DIR/concat.rs:14:13 + | +LL | concat!(foo); + | ^^^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: expected a literal + --> $DIR/concat.rs:16:13 + | +LL | concat!(foo()); + | ^^^^^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: cannot concatenate a byte string literal with string literals + --> $DIR/concat.rs:19:20 + | +LL | concat!("abc", b"def", 'g', "hi", b"jkl"); + | ----- ^^^^^^ --- ---- ^^^^^^ byte string literal + | | | | | + | | | | string literal + | | | string literal + | | byte string literal + | string literal + | + = help: do not mix byte string literals and string literals +help: you can use byte string literals + | +LL | concat!(b"abc", b"def", b'g', b"hi", b"jkl"); + | ^ ^ ^ + +error: aborting due to 3 previous errors + From 764ca0dab735a84effb42f4785afd6af34e34087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 31 Jul 2018 10:34:53 -0700 Subject: [PATCH 3/5] review comments --- src/libsyntax/ast.rs | 5 ----- src/libsyntax/ext/build.rs | 6 ++++++ src/libsyntax_ext/concat.rs | 5 +---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 44cfd8833336a..1b6b47f5489d7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1300,11 +1300,6 @@ impl LitKind { } } - /// Returns a `LitKind::ByteStr` from `content`. - pub fn new_byte_str(content: Vec) -> LitKind { - LitKind::ByteStr(Lrc::new(content)) - } - /// Returns true if this is a numeric literal. pub fn is_numeric(&self) -> bool { match *self { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 6135650766569..1e511c23bde4e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi::Abi; use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; use attr; @@ -145,6 +146,7 @@ pub trait AstBuilder { fn expr_vec_ng(&self, sp: Span) -> P; fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P; fn expr_str(&self, sp: Span, s: Symbol) -> P; + fn expr_byte_str(&self, sp: Span, byte_str: Vec) -> P; fn expr_some(&self, sp: Span, expr: P) -> P; fn expr_none(&self, sp: Span) -> P; @@ -736,6 +738,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) } + fn expr_byte_str(&self, sp: Span, byte_str: Vec) -> P { + self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(byte_str))) + } + fn expr_cast(&self, sp: Span, expr: P, ty: P) -> P { self.expr(sp, ast::ExprKind::Cast(expr, ty)) } diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index a5d04b6acc1fa..b53b54e0b933e 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -98,10 +98,7 @@ pub fn expand_syntax_ext( } let sp = sp.apply_mark(cx.current_expansion.mark); if b_accumulator.len() > 0 { - base::MacEager::expr(cx.expr_lit( - sp, - ast::LitKind::new_byte_str(b_accumulator), - )) + base::MacEager::expr(cx.expr_byte_str(sp, b_accumulator)) } else { base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string_accumulator))) } From 81f402f243f81fc7eaafa28bee66a3f164b788ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 31 Jul 2018 11:02:48 -0700 Subject: [PATCH 4/5] Add stub of `concat!("", b"")` support while still emitting error --- src/libsyntax_ext/concat.rs | 17 +++++++++++++---- src/libsyntax_ext/lib.rs | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index b53b54e0b933e..c6eac42884998 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -30,6 +30,9 @@ pub fn expand_syntax_ext( let mut string_pos = vec![]; let mut b_accumulator: Vec = vec![]; let mut b_pos: Vec = vec![]; + // We don't support mixing things with byte str literals, but do a best effort to fill in a + // reasonable byte str output to avoid further errors down the line. + let mut unified_accumulator: Vec = vec![]; let mut missing_literal = vec![]; for e in es { match e.node { @@ -39,28 +42,34 @@ pub fn expand_syntax_ext( | ast::LitKind::FloatUnsuffixed(ref s) => { string_accumulator.push_str(&s.as_str()); string_pos.push(e.span); + unified_accumulator.extend(s.to_string().into_bytes()); } ast::LitKind::Char(c) => { string_accumulator.push(c); string_pos.push(e.span); + unified_accumulator.extend(c.to_string().into_bytes()); } ast::LitKind::Int(i, ast::LitIntType::Unsigned(_)) | ast::LitKind::Int(i, ast::LitIntType::Signed(_)) | ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => { string_accumulator.push_str(&i.to_string()); string_pos.push(e.span); + unified_accumulator.extend(i.to_bytes().iter()); } ast::LitKind::Bool(b) => { string_accumulator.push_str(&b.to_string()); string_pos.push(e.span); + unified_accumulator.push(b as u8); } ast::LitKind::Byte(byte) => { b_accumulator.push(byte); b_pos.push(e.span); + unified_accumulator.push(byte); } ast::LitKind::ByteStr(ref b_str) => { b_accumulator.extend(b_str.iter()); b_pos.push(e.span); + unified_accumulator.extend(b_str.iter()); } }, _ => { @@ -73,7 +82,8 @@ pub fn expand_syntax_ext( err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); } - // Do not allow mixing "" and b"" + let sp = sp.apply_mark(cx.current_expansion.mark); + // Do not allow mixing "" and b"", but return the joint b"" to avoid further errors if string_accumulator.len() > 0 && b_accumulator.len() > 0 { let mut err = cx.struct_span_err( b_pos.clone(), @@ -95,9 +105,8 @@ pub fn expand_syntax_ext( .collect(), ); err.emit(); - } - let sp = sp.apply_mark(cx.current_expansion.mark); - if b_accumulator.len() > 0 { + base::MacEager::expr(cx.expr_byte_str(sp, unified_accumulator)) + } else if b_accumulator.len() > 0 { base::MacEager::expr(cx.expr_byte_str(sp, b_accumulator)) } else { base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string_accumulator))) diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index f0d33835cd0fb..0052eb75f6aaf 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -14,8 +14,9 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(proc_macro_internals)] #![feature(decl_macro)] +#![feature(int_to_from_bytes)] +#![feature(proc_macro_internals)] #![feature(str_escape)] #![feature(rustc_diagnostic_macros)] From 2ab6205b4e14cd495bc3a0cb461ddbc5a90401d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 31 Jul 2018 13:00:21 -0700 Subject: [PATCH 5/5] Modify diagnostic to be more accurate --- src/libsyntax_ext/concat.rs | 70 +++++++++++++++++++++++++++-------- src/test/ui/concat.rs | 14 ++++++- src/test/ui/concat.stderr | 73 ++++++++++++++++++++++++++++++++++--- 3 files changed, 136 insertions(+), 21 deletions(-) diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index c6eac42884998..05f894aa85479 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -28,6 +28,8 @@ pub fn expand_syntax_ext( }; let mut string_accumulator = String::new(); let mut string_pos = vec![]; + let mut int_pos = vec![]; + let mut bool_pos = vec![]; let mut b_accumulator: Vec = vec![]; let mut b_pos: Vec = vec![]; // We don't support mixing things with byte str literals, but do a best effort to fill in a @@ -42,6 +44,8 @@ pub fn expand_syntax_ext( | ast::LitKind::FloatUnsuffixed(ref s) => { string_accumulator.push_str(&s.as_str()); string_pos.push(e.span); + // If we ever allow `concat!("", b"")`, we should probably add a warn by default + // lint to this code. unified_accumulator.extend(s.to_string().into_bytes()); } ast::LitKind::Char(c) => { @@ -53,13 +57,19 @@ pub fn expand_syntax_ext( | ast::LitKind::Int(i, ast::LitIntType::Signed(_)) | ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => { string_accumulator.push_str(&i.to_string()); - string_pos.push(e.span); + int_pos.push(e.span); + // If we ever allow `concat!()` mixing byte literals with integers, we need to + // define the appropriate behavior for it. Consistently considering them as + // "machine width" would be bug-prone. Taking the smallest possible size for the + // literal is probably what people _that don't think about it_ would expect, but + // would be inconsistent. Another option is only to accept the literals if they + // would fit in a `u8`. unified_accumulator.extend(i.to_bytes().iter()); } ast::LitKind::Bool(b) => { string_accumulator.push_str(&b.to_string()); - string_pos.push(e.span); - unified_accumulator.push(b as u8); + bool_pos.push(e.span); + // would `concat!(true, b"asdf")` ever make sense? } ast::LitKind::Byte(byte) => { b_accumulator.push(byte); @@ -71,8 +81,10 @@ pub fn expand_syntax_ext( b_pos.push(e.span); unified_accumulator.extend(b_str.iter()); } - }, + } _ => { + // Consider the possibility of allowing `concat!(b"asdf", [1, 2, 3, 4])`, given + // that every single element of the array is a valid `u8`. missing_literal.push(e.span); } } @@ -84,26 +96,54 @@ pub fn expand_syntax_ext( } let sp = sp.apply_mark(cx.current_expansion.mark); // Do not allow mixing "" and b"", but return the joint b"" to avoid further errors - if string_accumulator.len() > 0 && b_accumulator.len() > 0 { + if b_pos.len() > 0 && (string_pos.len() > 0 || int_pos.len() > 0 || bool_pos.len() > 0) { + let mut mixings = vec![]; + if string_pos.len() > 0 { + mixings.push("string"); + } + if int_pos.len() > 0 { + mixings.push("numeric"); + } + if bool_pos.len() > 0 { + mixings.push("boolean"); + } let mut err = cx.struct_span_err( b_pos.clone(), - "cannot concatenate a byte string literal with string literals", + "cannot concatenate a byte string literal with other literals", ); + if mixings.len() > 0 && (int_pos.len() > 0 || bool_pos.len() > 0) { + let msg = if mixings.len() >= 2 { + format!( + "{} or {}", + mixings[0..mixings.len() - 1].join(", "), + mixings.last().unwrap(), + ) + } else { + mixings[0].to_string() + }; + err.note(&format!("we don't support mixing {} literals and byte strings", msg)); + } + if string_pos.len() > 0 && int_pos.len() == 0 && bool_pos.len() == 0 { + err.multipart_suggestion( + "we don't support mixing string and byte string literals, use only byte strings", + string_pos + .iter() + .map(|pos| (pos.shrink_to_lo(), "b".to_string())) + .collect(), + ); + } for pos in &b_pos { err.span_label(*pos, "byte string literal"); } for pos in &string_pos { err.span_label(*pos, "string literal"); - } - err.help("do not mix byte string literals and string literals"); - err.multipart_suggestion( - "you can use byte string literals", - string_pos - .iter() - .map(|pos| (pos.shrink_to_lo(), "b".to_string())) - .collect(), - ); + for pos in &int_pos { + err.span_label(*pos, "numeric literal"); + } + for pos in &bool_pos { + err.span_label(*pos, "boolean literal"); + } err.emit(); base::MacEager::expr(cx.expr_byte_str(sp, unified_accumulator)) } else if b_accumulator.len() > 0 { diff --git a/src/test/ui/concat.rs b/src/test/ui/concat.rs index 9f2ace52df571..f654ae299276a 100644 --- a/src/test/ui/concat.rs +++ b/src/test/ui/concat.rs @@ -17,6 +17,18 @@ fn main() { //~^ ERROR: expected a literal concat!(b'a', b"bc", b"def"); concat!("abc", b"def", 'g', "hi", b"jkl"); - //~^ ERROR cannot concatenate a byte string literal with string literals + //~^ ERROR cannot concatenate a byte string literal with other literals // `concat!()` cannot mix "" and b"" literals (it might allow it in the future) + concat!(1, b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals + concat!(true, b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals + concat!(1, true, b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals + concat!(1, true, "abc", b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals + concat!(true, "abc", b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals + concat!(1, "abc", b"def"); + //~^ ERROR cannot concatenate a byte string literal with other literals } diff --git a/src/test/ui/concat.stderr b/src/test/ui/concat.stderr index f1aa766cd0e5d..1eccedd111303 100644 --- a/src/test/ui/concat.stderr +++ b/src/test/ui/concat.stderr @@ -14,7 +14,7 @@ LL | concat!(foo()); | = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` -error: cannot concatenate a byte string literal with string literals +error: cannot concatenate a byte string literal with other literals --> $DIR/concat.rs:19:20 | LL | concat!("abc", b"def", 'g', "hi", b"jkl"); @@ -24,12 +24,75 @@ LL | concat!("abc", b"def", 'g', "hi", b"jkl"); | | | string literal | | byte string literal | string literal - | - = help: do not mix byte string literals and string literals -help: you can use byte string literals +help: we don't support mixing string and byte string literals, use only byte strings | LL | concat!(b"abc", b"def", b'g', b"hi", b"jkl"); | ^ ^ ^ -error: aborting due to 3 previous errors +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:22:16 + | +LL | concat!(1, b"def"); + | - ^^^^^^ byte string literal + | | + | numeric literal + | + = note: we don't support mixing numeric literals and byte strings + +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:24:19 + | +LL | concat!(true, b"def"); + | ---- ^^^^^^ byte string literal + | | + | boolean literal + | + = note: we don't support mixing boolean literals and byte strings + +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:26:22 + | +LL | concat!(1, true, b"def"); + | - ---- ^^^^^^ byte string literal + | | | + | | boolean literal + | numeric literal + | + = note: we don't support mixing numeric or boolean literals and byte strings + +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:28:29 + | +LL | concat!(1, true, "abc", b"def"); + | - ---- ----- ^^^^^^ byte string literal + | | | | + | | | string literal + | | boolean literal + | numeric literal + | + = note: we don't support mixing string, numeric or boolean literals and byte strings + +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:30:26 + | +LL | concat!(true, "abc", b"def"); + | ---- ----- ^^^^^^ byte string literal + | | | + | | string literal + | boolean literal + | + = note: we don't support mixing string or boolean literals and byte strings + +error: cannot concatenate a byte string literal with other literals + --> $DIR/concat.rs:32:23 + | +LL | concat!(1, "abc", b"def"); + | - ----- ^^^^^^ byte string literal + | | | + | | string literal + | numeric literal + | + = note: we don't support mixing string or numeric literals and byte strings + +error: aborting due to 9 previous errors