Rollup merge of #142698 - tgross35:concat-byte-cstr-diag, r=petrochenkov
Improve diagnostics for `concat_bytes!` with C string literals Use the same error as other invalid types for `concat_bytes!`, rather than using `ConcatCStrLit` from `concat!`. Also add more information with a note about why this doesn't work, and a suggestion to use a null-terminated byte string instead.
This commit is contained in:
commit
c693bc268a
5 changed files with 136 additions and 39 deletions
|
|
@ -104,6 +104,8 @@ builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
|
|||
builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
|
||||
.byte_char = try using a byte character
|
||||
.byte_str = try using a byte string
|
||||
.c_str = try using a null-terminated byte string
|
||||
.c_str_note = concatenating C strings is ambiguous about including the '\0'
|
||||
.number_array = try wrapping the number in an array
|
||||
|
||||
builtin_macros_concat_bytes_missing_literal = expected a byte literal
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{ExprKind, LitIntType, LitKind, UintTy, token};
|
||||
use rustc_ast::{ExprKind, LitIntType, LitKind, StrStyle, UintTy, token};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
|
|
@ -21,15 +21,32 @@ fn invalid_type_err(
|
|||
let snippet = cx.sess.source_map().span_to_snippet(span).ok();
|
||||
let dcx = cx.dcx();
|
||||
match LitKind::from_token_lit(token_lit) {
|
||||
Ok(LitKind::CStr(_, _)) => {
|
||||
Ok(LitKind::CStr(_, style)) => {
|
||||
// Avoid ambiguity in handling of terminal `NUL` by refusing to
|
||||
// concatenate C string literals as bytes.
|
||||
dcx.emit_err(errors::ConcatCStrLit { span })
|
||||
let sugg = if let Some(mut as_bstr) = snippet
|
||||
&& style == StrStyle::Cooked
|
||||
&& as_bstr.starts_with('c')
|
||||
&& as_bstr.ends_with('"')
|
||||
{
|
||||
// Suggest`c"foo"` -> `b"foo\0"` if we can
|
||||
as_bstr.replace_range(0..1, "b");
|
||||
as_bstr.pop();
|
||||
as_bstr.push_str(r#"\0""#);
|
||||
Some(ConcatBytesInvalidSuggestion::CStrLit { span, as_bstr })
|
||||
} else {
|
||||
// No suggestion for a missing snippet, raw strings, or if for some reason we have
|
||||
// a span that doesn't match `c"foo"` (possible if a proc macro assigns a span
|
||||
// that doesn't actually point to a C string).
|
||||
None
|
||||
};
|
||||
// We can only provide a suggestion if we have a snip and it is not a raw string
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "C string", sugg, cs_note: Some(()) })
|
||||
}
|
||||
Ok(LitKind::Char(_)) => {
|
||||
let sugg =
|
||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg })
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg, cs_note: None })
|
||||
}
|
||||
Ok(LitKind::Str(_, _)) => {
|
||||
// suggestion would be invalid if we are nested
|
||||
|
|
@ -38,18 +55,21 @@ fn invalid_type_err(
|
|||
} else {
|
||||
None
|
||||
};
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg })
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg, cs_note: None })
|
||||
}
|
||||
Ok(LitKind::Float(_, _)) => {
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None })
|
||||
}
|
||||
Ok(LitKind::Bool(_)) => {
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None })
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None, cs_note: None })
|
||||
}
|
||||
Ok(LitKind::Bool(_)) => dcx.emit_err(ConcatBytesInvalid {
|
||||
span,
|
||||
lit_kind: "boolean",
|
||||
sugg: None,
|
||||
cs_note: None,
|
||||
}),
|
||||
Ok(LitKind::Int(_, _)) if !is_nested => {
|
||||
let sugg =
|
||||
snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span, snippet });
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg })
|
||||
dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg, cs_note: None })
|
||||
}
|
||||
Ok(LitKind::Int(val, LitIntType::Unsuffixed | LitIntType::Unsigned(UintTy::U8))) => {
|
||||
assert!(val.get() > u8::MAX.into()); // must be an error
|
||||
|
|
|
|||
|
|
@ -215,6 +215,8 @@ pub(crate) struct ConcatBytesInvalid {
|
|||
pub(crate) lit_kind: &'static str,
|
||||
#[subdiagnostic]
|
||||
pub(crate) sugg: Option<ConcatBytesInvalidSuggestion>,
|
||||
#[note(builtin_macros_c_str_note)]
|
||||
pub(crate) cs_note: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
|
|
@ -239,6 +241,13 @@ pub(crate) enum ConcatBytesInvalidSuggestion {
|
|||
span: Span,
|
||||
snippet: String,
|
||||
},
|
||||
#[note(builtin_macros_c_str_note)]
|
||||
#[suggestion(builtin_macros_c_str, code = "{as_bstr}", applicability = "machine-applicable")]
|
||||
CStrLit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
as_bstr: String,
|
||||
},
|
||||
#[suggestion(
|
||||
builtin_macros_number_array,
|
||||
code = "[{snippet}]",
|
||||
|
|
|
|||
|
|
@ -1,20 +1,44 @@
|
|||
//@ edition: 2021
|
||||
// 2021 edition for C string literals
|
||||
|
||||
#![feature(concat_bytes)]
|
||||
|
||||
fn main() {
|
||||
// Identifiers
|
||||
concat_bytes!(pie); //~ ERROR expected a byte literal
|
||||
concat_bytes!(pie, pie); //~ ERROR expected a byte literal
|
||||
|
||||
// String literals
|
||||
concat_bytes!("tnrsi", "tnri"); //~ ERROR cannot concatenate string literals
|
||||
//~^ SUGGESTION b"tnrsi"
|
||||
concat_bytes!(r"tnrsi", r"tnri"); //~ ERROR cannot concatenate string literals
|
||||
//~^ SUGGESTION br"tnrsi"
|
||||
concat_bytes!(r#"tnrsi"#, r###"tnri"###); //~ ERROR cannot concatenate string literals
|
||||
//~^ SUGGESTION br#"tnrsi"#
|
||||
concat_bytes!(c"tnrsi", c"tnri"); //~ ERROR cannot concatenate C string literals
|
||||
//~^ SUGGESTION b"tnrsi\0"
|
||||
concat_bytes!(cr"tnrsi", cr"tnri"); //~ ERROR cannot concatenate C string literals
|
||||
concat_bytes!(cr#"tnrsi"#, cr###"tnri"###); //~ ERROR cannot concatenate C string literals
|
||||
|
||||
// Other literals
|
||||
concat_bytes!(2.8); //~ ERROR cannot concatenate float literals
|
||||
concat_bytes!(300); //~ ERROR cannot concatenate numeric literals
|
||||
//~^ SUGGESTION [300]
|
||||
concat_bytes!('a'); //~ ERROR cannot concatenate character literals
|
||||
//~^ SUGGESTION b'a'
|
||||
concat_bytes!(true, false); //~ ERROR cannot concatenate boolean literals
|
||||
concat_bytes!(42, b"va", b'l'); //~ ERROR cannot concatenate numeric literals
|
||||
//~^ SUGGESTION [42]
|
||||
concat_bytes!(42, b"va", b'l', [1, 2]); //~ ERROR cannot concatenate numeric literals
|
||||
//~^ SUGGESTION [42]
|
||||
|
||||
// Nested items
|
||||
concat_bytes!([
|
||||
"hi", //~ ERROR cannot concatenate string literals
|
||||
]);
|
||||
concat_bytes!([
|
||||
'a', //~ ERROR cannot concatenate character literals
|
||||
//~^ SUGGESTION b'a'
|
||||
]);
|
||||
concat_bytes!([
|
||||
true, //~ ERROR cannot concatenate boolean literals
|
||||
|
|
@ -38,6 +62,7 @@ fn main() {
|
|||
[5, 6, 7], //~ ERROR cannot concatenate doubly nested array
|
||||
]);
|
||||
concat_bytes!(5u16); //~ ERROR cannot concatenate numeric literals
|
||||
//~^ SUGGESTION [5u16]
|
||||
concat_bytes!([5u16]); //~ ERROR numeric literal is not a `u8`
|
||||
concat_bytes!([3; ()]); //~ ERROR repeat count is not a positive number
|
||||
concat_bytes!([3; -2]); //~ ERROR repeat count is not a positive number
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: expected a byte literal
|
||||
--> $DIR/concat-bytes-error.rs:4:19
|
||||
--> $DIR/concat-bytes-error.rs:8:19
|
||||
|
|
||||
LL | concat_bytes!(pie);
|
||||
| ^^^
|
||||
|
|
@ -7,7 +7,7 @@ LL | concat_bytes!(pie);
|
|||
= note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
|
||||
|
||||
error: expected a byte literal
|
||||
--> $DIR/concat-bytes-error.rs:5:19
|
||||
--> $DIR/concat-bytes-error.rs:9:19
|
||||
|
|
||||
LL | concat_bytes!(pie, pie);
|
||||
| ^^^ ^^^
|
||||
|
|
@ -15,85 +15,126 @@ LL | concat_bytes!(pie, pie);
|
|||
= note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
|
||||
|
||||
error: cannot concatenate string literals
|
||||
--> $DIR/concat-bytes-error.rs:6:19
|
||||
--> $DIR/concat-bytes-error.rs:12:19
|
||||
|
|
||||
LL | concat_bytes!("tnrsi", "tnri");
|
||||
| ^^^^^^^ help: try using a byte string: `b"tnrsi"`
|
||||
|
||||
error: cannot concatenate string literals
|
||||
--> $DIR/concat-bytes-error.rs:14:19
|
||||
|
|
||||
LL | concat_bytes!(r"tnrsi", r"tnri");
|
||||
| ^^^^^^^^ help: try using a byte string: `br"tnrsi"`
|
||||
|
||||
error: cannot concatenate string literals
|
||||
--> $DIR/concat-bytes-error.rs:16:19
|
||||
|
|
||||
LL | concat_bytes!(r#"tnrsi"#, r###"tnri"###);
|
||||
| ^^^^^^^^^^ help: try using a byte string: `br#"tnrsi"#`
|
||||
|
||||
error: cannot concatenate C string literals
|
||||
--> $DIR/concat-bytes-error.rs:18:19
|
||||
|
|
||||
LL | concat_bytes!(c"tnrsi", c"tnri");
|
||||
| ^^^^^^^^ help: try using a null-terminated byte string: `b"tnrsi\0"`
|
||||
|
|
||||
note: concatenating C strings is ambiguous about including the '\0'
|
||||
--> $DIR/concat-bytes-error.rs:18:19
|
||||
|
|
||||
LL | concat_bytes!(c"tnrsi", c"tnri");
|
||||
| ^^^^^^^^
|
||||
= note: concatenating C strings is ambiguous about including the '\0'
|
||||
|
||||
error: cannot concatenate C string literals
|
||||
--> $DIR/concat-bytes-error.rs:20:19
|
||||
|
|
||||
LL | concat_bytes!(cr"tnrsi", cr"tnri");
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: concatenating C strings is ambiguous about including the '\0'
|
||||
|
||||
error: cannot concatenate C string literals
|
||||
--> $DIR/concat-bytes-error.rs:21:19
|
||||
|
|
||||
LL | concat_bytes!(cr#"tnrsi"#, cr###"tnri"###);
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: concatenating C strings is ambiguous about including the '\0'
|
||||
|
||||
error: cannot concatenate float literals
|
||||
--> $DIR/concat-bytes-error.rs:7:19
|
||||
--> $DIR/concat-bytes-error.rs:24:19
|
||||
|
|
||||
LL | concat_bytes!(2.8);
|
||||
| ^^^
|
||||
|
||||
error: cannot concatenate numeric literals
|
||||
--> $DIR/concat-bytes-error.rs:8:19
|
||||
--> $DIR/concat-bytes-error.rs:25:19
|
||||
|
|
||||
LL | concat_bytes!(300);
|
||||
| ^^^ help: try wrapping the number in an array: `[300]`
|
||||
|
||||
error: cannot concatenate character literals
|
||||
--> $DIR/concat-bytes-error.rs:9:19
|
||||
--> $DIR/concat-bytes-error.rs:27:19
|
||||
|
|
||||
LL | concat_bytes!('a');
|
||||
| ^^^ help: try using a byte character: `b'a'`
|
||||
|
||||
error: cannot concatenate boolean literals
|
||||
--> $DIR/concat-bytes-error.rs:10:19
|
||||
--> $DIR/concat-bytes-error.rs:29:19
|
||||
|
|
||||
LL | concat_bytes!(true, false);
|
||||
| ^^^^
|
||||
|
||||
error: cannot concatenate numeric literals
|
||||
--> $DIR/concat-bytes-error.rs:11:19
|
||||
--> $DIR/concat-bytes-error.rs:30:19
|
||||
|
|
||||
LL | concat_bytes!(42, b"va", b'l');
|
||||
| ^^ help: try wrapping the number in an array: `[42]`
|
||||
|
||||
error: cannot concatenate numeric literals
|
||||
--> $DIR/concat-bytes-error.rs:12:19
|
||||
--> $DIR/concat-bytes-error.rs:32:19
|
||||
|
|
||||
LL | concat_bytes!(42, b"va", b'l', [1, 2]);
|
||||
| ^^ help: try wrapping the number in an array: `[42]`
|
||||
|
||||
error: cannot concatenate string literals
|
||||
--> $DIR/concat-bytes-error.rs:14:9
|
||||
--> $DIR/concat-bytes-error.rs:37:9
|
||||
|
|
||||
LL | "hi",
|
||||
| ^^^^
|
||||
|
||||
error: cannot concatenate character literals
|
||||
--> $DIR/concat-bytes-error.rs:17:9
|
||||
--> $DIR/concat-bytes-error.rs:40:9
|
||||
|
|
||||
LL | 'a',
|
||||
| ^^^ help: try using a byte character: `b'a'`
|
||||
|
||||
error: cannot concatenate boolean literals
|
||||
--> $DIR/concat-bytes-error.rs:20:9
|
||||
--> $DIR/concat-bytes-error.rs:44:9
|
||||
|
|
||||
LL | true,
|
||||
| ^^^^
|
||||
|
||||
error: cannot concatenate boolean literals
|
||||
--> $DIR/concat-bytes-error.rs:23:9
|
||||
--> $DIR/concat-bytes-error.rs:47:9
|
||||
|
|
||||
LL | false,
|
||||
| ^^^^^
|
||||
|
||||
error: cannot concatenate float literals
|
||||
--> $DIR/concat-bytes-error.rs:26:9
|
||||
--> $DIR/concat-bytes-error.rs:50:9
|
||||
|
|
||||
LL | 2.6,
|
||||
| ^^^
|
||||
|
||||
error: numeric literal is out of bounds
|
||||
--> $DIR/concat-bytes-error.rs:29:9
|
||||
--> $DIR/concat-bytes-error.rs:53:9
|
||||
|
|
||||
LL | 265,
|
||||
| ^^^
|
||||
|
||||
error: expected a byte literal
|
||||
--> $DIR/concat-bytes-error.rs:32:9
|
||||
--> $DIR/concat-bytes-error.rs:56:9
|
||||
|
|
||||
LL | -33,
|
||||
| ^^^
|
||||
|
|
@ -101,7 +142,7 @@ LL | -33,
|
|||
= note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
|
||||
|
||||
error: cannot concatenate doubly nested array
|
||||
--> $DIR/concat-bytes-error.rs:35:9
|
||||
--> $DIR/concat-bytes-error.rs:59:9
|
||||
|
|
||||
LL | b"hi!",
|
||||
| ^^^^^^
|
||||
|
|
@ -110,43 +151,43 @@ LL | b"hi!",
|
|||
= help: try flattening the array
|
||||
|
||||
error: cannot concatenate doubly nested array
|
||||
--> $DIR/concat-bytes-error.rs:38:9
|
||||
--> $DIR/concat-bytes-error.rs:62:9
|
||||
|
|
||||
LL | [5, 6, 7],
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: cannot concatenate numeric literals
|
||||
--> $DIR/concat-bytes-error.rs:40:19
|
||||
--> $DIR/concat-bytes-error.rs:64:19
|
||||
|
|
||||
LL | concat_bytes!(5u16);
|
||||
| ^^^^ help: try wrapping the number in an array: `[5u16]`
|
||||
|
||||
error: numeric literal is not a `u8`
|
||||
--> $DIR/concat-bytes-error.rs:41:20
|
||||
--> $DIR/concat-bytes-error.rs:66:20
|
||||
|
|
||||
LL | concat_bytes!([5u16]);
|
||||
| ^^^^
|
||||
|
||||
error: repeat count is not a positive number
|
||||
--> $DIR/concat-bytes-error.rs:42:23
|
||||
--> $DIR/concat-bytes-error.rs:67:23
|
||||
|
|
||||
LL | concat_bytes!([3; ()]);
|
||||
| ^^
|
||||
|
||||
error: repeat count is not a positive number
|
||||
--> $DIR/concat-bytes-error.rs:43:23
|
||||
--> $DIR/concat-bytes-error.rs:68:23
|
||||
|
|
||||
LL | concat_bytes!([3; -2]);
|
||||
| ^^
|
||||
|
||||
error: repeat count is not a positive number
|
||||
--> $DIR/concat-bytes-error.rs:44:25
|
||||
--> $DIR/concat-bytes-error.rs:69:25
|
||||
|
|
||||
LL | concat_bytes!([pie; -2]);
|
||||
| ^^
|
||||
|
||||
error: expected a byte literal
|
||||
--> $DIR/concat-bytes-error.rs:45:20
|
||||
--> $DIR/concat-bytes-error.rs:70:20
|
||||
|
|
||||
LL | concat_bytes!([pie; 2]);
|
||||
| ^^^
|
||||
|
|
@ -154,28 +195,28 @@ LL | concat_bytes!([pie; 2]);
|
|||
= note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
|
||||
|
||||
error: cannot concatenate float literals
|
||||
--> $DIR/concat-bytes-error.rs:46:20
|
||||
--> $DIR/concat-bytes-error.rs:71:20
|
||||
|
|
||||
LL | concat_bytes!([2.2; 0]);
|
||||
| ^^^
|
||||
|
||||
error: repeat count is not a positive number
|
||||
--> $DIR/concat-bytes-error.rs:47:25
|
||||
--> $DIR/concat-bytes-error.rs:72:25
|
||||
|
|
||||
LL | concat_bytes!([5.5; ()]);
|
||||
| ^^
|
||||
|
||||
error: cannot concatenate doubly nested array
|
||||
--> $DIR/concat-bytes-error.rs:48:20
|
||||
--> $DIR/concat-bytes-error.rs:73:20
|
||||
|
|
||||
LL | concat_bytes!([[1, 2, 3]; 3]);
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: cannot concatenate doubly nested array
|
||||
--> $DIR/concat-bytes-error.rs:49:20
|
||||
--> $DIR/concat-bytes-error.rs:74:20
|
||||
|
|
||||
LL | concat_bytes!([[42; 2]; 3]);
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 33 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue