Reserve guarded string literals (RFC 3593)

This commit is contained in:
Peter Jaszkowiak 2024-04-14 17:37:45 -06:00
parent 6f4ae0f345
commit 321a5db7d4
23 changed files with 1514 additions and 9 deletions

View File

@ -104,6 +104,12 @@ pub enum TokenKind {
/// for emoji identifier recovery, as those are not meant to be ever accepted. /// for emoji identifier recovery, as those are not meant to be ever accepted.
InvalidPrefix, InvalidPrefix,
/// Guarded string literal prefix: `#"` or `##`.
///
/// Used for reserving "guarded strings" (RFC 3598) in edition 2024.
/// Split into the component tokens on older editions.
GuardedStrPrefix,
/// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid
/// suffix, but may be present here on string and float literals. Users of /// suffix, but may be present here on string and float literals. Users of
/// this type will need to check for and reject that case. /// this type will need to check for and reject that case.
@ -191,30 +197,41 @@ pub enum DocStyle {
/// `rustc_ast::ast::LitKind`). /// `rustc_ast::ast::LitKind`).
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum LiteralKind { pub enum LiteralKind {
/// "12_u8", "0o100", "0b120i99", "1f32". /// `12_u8`, `0o100`, `0b120i99`, `1f32`.
Int { base: Base, empty_int: bool }, Int { base: Base, empty_int: bool },
/// "12.34f32", "1e3", but not "1f32". /// `12.34f32`, `1e3`, but not `1f32`.
Float { base: Base, empty_exponent: bool }, Float { base: Base, empty_exponent: bool },
/// "'a'", "'\\'", "'''", "';" /// `'a'`, `'\\'`, `'''`, `';`
Char { terminated: bool }, Char { terminated: bool },
/// "b'a'", "b'\\'", "b'''", "b';" /// `b'a'`, `b'\\'`, `b'''`, `b';`
Byte { terminated: bool }, Byte { terminated: bool },
/// ""abc"", ""abc" /// `"abc"`, `"abc`
Str { terminated: bool }, Str { terminated: bool },
/// "b"abc"", "b"abc" /// `b"abc"`, `b"abc`
ByteStr { terminated: bool }, ByteStr { terminated: bool },
/// `c"abc"`, `c"abc` /// `c"abc"`, `c"abc`
CStr { terminated: bool }, CStr { terminated: bool },
/// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a". `None` indicates /// `r"abc"`, `r#"abc"#`, `r####"ab"###"c"####`, `r#"a`. `None` indicates
/// an invalid literal. /// an invalid literal.
RawStr { n_hashes: Option<u8> }, RawStr { n_hashes: Option<u8> },
/// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a". `None` /// `br"abc"`, `br#"abc"#`, `br####"ab"###"c"####`, `br#"a`. `None`
/// indicates an invalid literal. /// indicates an invalid literal.
RawByteStr { n_hashes: Option<u8> }, RawByteStr { n_hashes: Option<u8> },
/// `cr"abc"`, "cr#"abc"#", `cr#"a`. `None` indicates an invalid literal. /// `cr"abc"`, "cr#"abc"#", `cr#"a`. `None` indicates an invalid literal.
RawCStr { n_hashes: Option<u8> }, RawCStr { n_hashes: Option<u8> },
} }
/// `#"abc"#`, `##"a"` (fewer closing), or even `#"a` (unterminated).
///
/// Can capture fewer closing hashes than starting hashes,
/// for more efficient lexing and better backwards diagnostics.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct GuardedStr {
pub n_hashes: u32,
pub terminated: bool,
pub token_len: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum RawStrError { pub enum RawStrError {
/// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##` /// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##`
@ -403,6 +420,12 @@ pub fn advance_token(&mut self) -> Token {
TokenKind::Literal { kind: literal_kind, suffix_start } TokenKind::Literal { kind: literal_kind, suffix_start }
} }
// Guarded string literal prefix: `#"` or `##`
'#' if matches!(self.first(), '"' | '#') => {
self.bump();
TokenKind::GuardedStrPrefix
}
// One-symbol tokens. // One-symbol tokens.
';' => Semi, ';' => Semi,
',' => Comma, ',' => Comma,
@ -780,6 +803,60 @@ fn double_quoted_string(&mut self) -> bool {
false false
} }
/// Attempt to lex for a guarded string literal.
///
/// Used by `rustc_parse::lexer` to lex for guarded strings
/// conditionally based on edition.
///
/// Note: this will not reset the `Cursor` when a
/// guarded string is not found. It is the caller's
/// responsibility to do so.
pub fn guarded_double_quoted_string(&mut self) -> Option<GuardedStr> {
debug_assert!(self.prev() != '#');
let mut n_start_hashes: u32 = 0;
while self.first() == '#' {
n_start_hashes += 1;
self.bump();
}
if self.first() != '"' {
return None;
}
self.bump();
debug_assert!(self.prev() == '"');
// Lex the string itself as a normal string literal
// so we can recover that for older editions later.
let terminated = self.double_quoted_string();
if !terminated {
let token_len = self.pos_within_token();
self.reset_pos_within_token();
return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len });
}
// Consume closing '#' symbols.
// Note that this will not consume extra trailing `#` characters:
// `###"abcde"####` is lexed as a `GuardedStr { n_end_hashes: 3, .. }`
// followed by a `#` token.
let mut n_end_hashes = 0;
while self.first() == '#' && n_end_hashes < n_start_hashes {
n_end_hashes += 1;
self.bump();
}
// Reserved syntax, always an error, so it doesn't matter if
// `n_start_hashes != n_end_hashes`.
self.eat_literal_suffix();
let token_len = self.pos_within_token();
self.reset_pos_within_token();
Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len })
}
/// Eats the double-quoted string and returns `n_hashes` and an error if encountered. /// Eats the double-quoted string and returns `n_hashes` and an error if encountered.
fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> { fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
// Wrap the actual function to handle the error with too many hashes. // Wrap the actual function to handle the error with too many hashes.

View File

@ -740,6 +740,9 @@ lint_reserved_prefix = prefix `{$prefix}` is unknown
.label = unknown prefix .label = unknown prefix
.suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021
lint_reserved_string = will be parsed as a guarded string in Rust 2024
.suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
lint_shadowed_into_iter = lint_shadowed_into_iter =
this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}
.use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity

View File

@ -176,6 +176,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
.decorate_lint(diag); .decorate_lint(diag);
} }
BuiltinLintDiag::ReservedString(suggestion) => {
lints::ReservedString { suggestion }.decorate_lint(diag);
}
BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
} }

View File

@ -3053,3 +3053,10 @@ pub(crate) enum MutRefSugg {
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(lint_unqualified_local_imports)] #[diag(lint_unqualified_local_imports)]
pub(crate) struct UnqualifiedLocalImportsDiag {} pub(crate) struct UnqualifiedLocalImportsDiag {}
#[derive(LintDiagnostic)]
#[diag(lint_reserved_string)]
pub(crate) struct ReservedString {
#[suggestion(code = " ", applicability = "machine-applicable")]
pub suggestion: Span,
}

View File

@ -92,6 +92,7 @@
RUST_2021_INCOMPATIBLE_OR_PATTERNS, RUST_2021_INCOMPATIBLE_OR_PATTERNS,
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
RUST_2021_PRELUDE_COLLISIONS, RUST_2021_PRELUDE_COLLISIONS,
RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
RUST_2024_INCOMPATIBLE_PAT, RUST_2024_INCOMPATIBLE_PAT,
RUST_2024_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS,
SELF_CONSTRUCTOR_FROM_OUTER_ITEM, SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
@ -4996,3 +4997,43 @@
Warn, Warn,
"detects pointer to integer transmutes in const functions and associated constants", "detects pointer to integer transmutes in const functions and associated constants",
} }
declare_lint! {
/// The `rust_2024_guarded_string_incompatible_syntax` lint detects `#` tokens
/// that will be parsed as part of a guarded string literal in Rust 2024.
///
/// ### Example
///
/// ```rust,edition2021,compile_fail
/// #![deny(rust_2024_guarded_string_incompatible_syntax)]
///
/// macro_rules! m {
/// (# $x:expr #) => ();
/// (# $x:expr) => ();
/// }
///
/// m!(#"hey"#);
/// m!(#"hello");
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Prior to Rust 2024, `#"hey"#` is three tokens: the first `#`
/// followed by the string literal `"hey"` then the final `#`.
/// In Rust 2024, the whole sequence is considered a single token.
///
/// This lint suggests to add whitespace between the leading `#`
/// and the string to keep them separated in Rust 2024.
// Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser.
#[allow(rustdoc::invalid_rust_codeblocks)]
pub RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
Allow,
"will be parsed as a guarded string in Rust 2024",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
reference: "issue #123735 <https://github.com/rust-lang/rust/issues/123735>",
};
crate_level_only
}

View File

@ -614,6 +614,8 @@ pub enum BuiltinLintDiag {
ReservedPrefix(Span, String), ReservedPrefix(Span, String),
/// `'r#` in edition < 2021. /// `'r#` in edition < 2021.
RawPrefix(Span), RawPrefix(Span),
/// `##` or `#"` is edition < 2024.
ReservedString(Span),
TrailingMacro(bool, Ident), TrailingMacro(bool, Ident),
BreakWithLabelAndLoop(Span), BreakWithLabelAndLoop(Span),
UnicodeTextFlow(Span, String), UnicodeTextFlow(Span, String),

View File

@ -706,6 +706,10 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow
.label = the label .label = the label
.suggestion = add `:` after the label .suggestion = add `:` after the label
parse_reserved_string = invalid string literal
.note = unprefixed guarded string literals are reserved for future use since Rust 2024
.suggestion_whitespace = consider inserting whitespace here
parse_return_types_use_thin_arrow = return types are denoted using `->` parse_return_types_use_thin_arrow = return types are denoted using `->`
.suggestion = use `->` instead .suggestion = use `->` instead

View File

@ -2110,6 +2110,24 @@ pub(crate) enum UnknownPrefixSugg {
}, },
} }
#[derive(Diagnostic)]
#[diag(parse_reserved_string)]
#[note]
pub(crate) struct ReservedString {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub sugg: Option<GuardedStringSugg>,
}
#[derive(Subdiagnostic)]
#[suggestion(
parse_suggestion_whitespace,
code = " ",
applicability = "maybe-incorrect",
style = "verbose"
)]
pub(crate) struct GuardedStringSugg(#[primary_span] pub Span);
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(parse_too_many_hashes)] #[diag(parse_too_many_hashes)]
pub(crate) struct TooManyHashes { pub(crate) struct TooManyHashes {

View File

@ -10,7 +10,8 @@
use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError};
use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::{ use rustc_session::lint::builtin::{
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
}; };
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -251,6 +252,7 @@ fn next_token(&mut self) -> (Token, bool) {
let prefix_span = self.mk_sp(start, lit_start); let prefix_span = self.mk_sp(start, lit_start);
return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace); return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace);
} }
rustc_lexer::TokenKind::GuardedStrPrefix => self.maybe_report_guarded_str(start, str_before),
rustc_lexer::TokenKind::Literal { kind, suffix_start } => { rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
let suffix_start = start + BytePos(suffix_start); let suffix_start = start + BytePos(suffix_start);
let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
@ -781,6 +783,86 @@ fn report_unknown_prefix(&self, start: BytePos) {
} }
} }
/// Detect guarded string literal syntax
///
/// RFC 3598 reserved this syntax for future use. As of Rust 2024,
/// using this syntax produces an error. In earlier editions, however, it
/// only results in an (allowed by default) lint, and is treated as
/// separate tokens.
fn maybe_report_guarded_str(&mut self, start: BytePos, str_before: &'src str) -> TokenKind {
let span = self.mk_sp(start, self.pos);
let edition2024 = span.edition().at_least_rust_2024();
let space_pos = start + BytePos(1);
let space_span = self.mk_sp(space_pos, space_pos);
let mut cursor = Cursor::new(str_before);
let (span, unterminated) = match cursor.guarded_double_quoted_string() {
Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => {
let end = start + BytePos(token_len);
let span = self.mk_sp(start, end);
let str_start = start + BytePos(n_hashes);
if edition2024 {
self.cursor = cursor;
self.pos = end;
}
let unterminated = if terminated { None } else { Some(str_start) };
(span, unterminated)
}
_ => {
// We should only get here in the `##+` case.
debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##");
(span, None)
}
};
if edition2024 {
if let Some(str_start) = unterminated {
// Only a fatal error if string is unterminated.
self.dcx()
.struct_span_fatal(
self.mk_sp(str_start, self.pos),
"unterminated double quote string",
)
.with_code(E0765)
.emit()
}
let sugg = if span.from_expansion() {
None
} else {
Some(errors::GuardedStringSugg(space_span))
};
// In Edition 2024 and later, emit a hard error.
let err = self.dcx().emit_err(errors::ReservedString { span, sugg });
token::Literal(token::Lit {
kind: token::Err(err),
symbol: self.symbol_from_to(start, self.pos),
suffix: None,
})
} else {
// Before Rust 2024, only emit a lint for migration.
self.psess.buffer_lint(
RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
span,
ast::CRATE_NODE_ID,
BuiltinLintDiag::ReservedString(space_span),
);
// For backwards compatibility, roll back to after just the first `#`
// and return the `Pound` token.
self.pos = start + BytePos(1);
self.cursor = Cursor::new(&str_before[1..]);
token::Pound
}
}
fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! { fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! {
self.dcx().emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num }); self.dcx().emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num });
} }

View File

@ -845,6 +845,7 @@ fn advance(
// Number literals. // Number literals.
LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number, LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,
}, },
TokenKind::GuardedStrPrefix => return no_highlight(sink),
TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => { TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => {
self.in_macro = true; self.in_macro = true;
sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) }); sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) });

View File

@ -187,6 +187,12 @@ fn extend_token(&mut self, kind: &rustc_lexer::TokenKind, token_text: &str) {
} }
rustc_lexer::TokenKind::RawIdent => IDENT, rustc_lexer::TokenKind::RawIdent => IDENT,
rustc_lexer::TokenKind::GuardedStrPrefix => {
err = "Invalid string literal (reserved syntax)";
ERROR
},
rustc_lexer::TokenKind::Literal { kind, .. } => { rustc_lexer::TokenKind::Literal { kind, .. } => {
self.extend_literal(token_text.len(), kind); self.extend_literal(token_text.len(), kind);
return; return;

View File

@ -0,0 +1,20 @@
//@ force-host
//@ edition:2021
//@ no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
use std::str::FromStr;
#[proc_macro]
pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream {
TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap()
}
#[proc_macro]
pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream {
TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap()
}

View File

@ -0,0 +1,21 @@
//@ force-host
//@ compile-flags: -Zunstable-options
//@ edition:2024
//@ no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
use std::str::FromStr;
#[proc_macro]
pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream {
TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap()
}
#[proc_macro]
pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream {
TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap()
}

View File

@ -0,0 +1,80 @@
//@ edition:2021
// ignore-tidy-linelength
#![warn(rust_2024_guarded_string_incompatible_syntax)]
macro_rules! demo2 {
( $a:tt $b:tt ) => { println!("two tokens") };
}
macro_rules! demo3 {
( $a:tt $b:tt $c:tt ) => { println!("three tokens") };
}
macro_rules! demo4 {
( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") };
}
macro_rules! demo5 {
( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") };
}
macro_rules! demo7 {
( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") };
}
fn main() {
demo3!(## "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(### "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(## "foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo7!(### "foo"###);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo5!(###"foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo5!(#"foo"###);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!("foo"###);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
// Non-ascii identifiers
demo2!(Ñ"foo");
//~^ ERROR prefix `Ñ` is unknown
demo4!(Ñ#""#);
//~^ ERROR prefix `Ñ` is unknown
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(🙃#"");
//~^ ERROR identifiers cannot contain emoji
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
}

View File

@ -0,0 +1,271 @@
error: prefix `Ñ` is unknown
--> $DIR/reserved-guarded-strings-lexing.rs:70:12
|
LL | demo2!(Ñ"foo");
| ^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
LL | demo2!(Ñ "foo");
| +
error: prefix `Ñ` is unknown
--> $DIR/reserved-guarded-strings-lexing.rs:72:12
|
LL | demo4!(Ñ#""#);
| ^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
LL | demo4!(Ñ #""#);
| +
error: identifiers cannot contain emoji: `🙃`
--> $DIR/reserved-guarded-strings-lexing.rs:76:12
|
LL | demo3!(🙃#"");
| ^^
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:28:12
|
LL | demo3!(## "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
note: the lint level is defined here
--> $DIR/reserved-guarded-strings-lexing.rs:4:9
|
LL | #![warn(rust_2024_guarded_string_incompatible_syntax)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# # "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:31:12
|
LL | demo4!(### "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(# ## "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:31:13
|
LL | demo4!(### "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(## # "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:36:12
|
LL | demo4!(## "foo"#);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(# # "foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:39:12
|
LL | demo7!(### "foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo7!(# ## "foo"###);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:39:13
|
LL | demo7!(### "foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo7!(## # "foo"###);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:39:21
|
LL | demo7!(### "foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo7!(### "foo"# ##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:39:22
|
LL | demo7!(### "foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo7!(### "foo"## #);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:49:12
|
LL | demo5!(###"foo"#);
| ^^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(# ##"foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:49:13
|
LL | demo5!(###"foo"#);
| ^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(## #"foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:49:14
|
LL | demo5!(###"foo"#);
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(### "foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:56:12
|
LL | demo5!(#"foo"###);
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(# "foo"###);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:56:18
|
LL | demo5!(#"foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(#"foo"# ##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:56:19
|
LL | demo5!(#"foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(#"foo"## #);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:63:17
|
LL | demo4!("foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!("foo"# ##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:63:18
|
LL | demo4!("foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!("foo"## #);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:72:13
|
LL | demo4!(Ñ#""#);
| ^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(Ñ# ""#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-lexing.rs:76:13
|
LL | demo3!(🙃#"");
| ^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(🙃# "");
| +
error: aborting due to 3 previous errors; 18 warnings emitted

View File

@ -0,0 +1,99 @@
//@ check-pass
//@ run-rustfix
//@ edition:2021
#![warn(rust_2024_guarded_string_incompatible_syntax)]
macro_rules! demo1 {
( $a:tt ) => { println!("one tokens") };
}
macro_rules! demo2 {
( $a:tt $b:tt ) => { println!("two tokens") };
}
macro_rules! demo3 {
( $a:tt $b:tt $c:tt ) => { println!("three tokens") };
}
macro_rules! demo4 {
( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") };
}
macro_rules! demo5 {
( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") };
}
macro_rules! demo6 {
( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") };
}
fn main() {
demo1!("");
demo2!(# "");
demo3!(# ""#);
demo2!(# "foo");
demo3!(# "foo"#);
demo2!("foo"#);
demo3!(# # "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(# # # "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(# # "foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo6!(# # # "foo"# #);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!("foo"# # #);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo2!(# "");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(# ""#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(# # "");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo2!(# "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(# # "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(# "foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(# # "foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo5!(# # "foo"# #);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
}

View File

@ -0,0 +1,99 @@
//@ check-pass
//@ run-rustfix
//@ edition:2021
#![warn(rust_2024_guarded_string_incompatible_syntax)]
macro_rules! demo1 {
( $a:tt ) => { println!("one tokens") };
}
macro_rules! demo2 {
( $a:tt $b:tt ) => { println!("two tokens") };
}
macro_rules! demo3 {
( $a:tt $b:tt $c:tt ) => { println!("three tokens") };
}
macro_rules! demo4 {
( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") };
}
macro_rules! demo5 {
( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") };
}
macro_rules! demo6 {
( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") };
}
fn main() {
demo1!("");
demo2!(# "");
demo3!(# ""#);
demo2!(# "foo");
demo3!(# "foo"#);
demo2!("foo"#);
demo3!(## "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(### "foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(## "foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo6!(### "foo"##);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!("foo"###);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo2!(#"");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(#""#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(##"");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo2!(#"foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(##"foo");
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo3!(#"foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo4!(##"foo"#);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
demo5!(##"foo"##);
//~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
//~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax]
//~| WARNING hard error in Rust 2024
}

View File

@ -0,0 +1,293 @@
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:40:12
|
LL | demo3!(## "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
note: the lint level is defined here
--> $DIR/reserved-guarded-strings-migration.rs:5:9
|
LL | #![warn(rust_2024_guarded_string_incompatible_syntax)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# # "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:43:12
|
LL | demo4!(### "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(# ## "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:43:13
|
LL | demo4!(### "foo");
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(## # "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:48:12
|
LL | demo4!(## "foo"#);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(# # "foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:51:12
|
LL | demo6!(### "foo"##);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo6!(# ## "foo"##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:51:13
|
LL | demo6!(### "foo"##);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo6!(## # "foo"##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:51:21
|
LL | demo6!(### "foo"##);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo6!(### "foo"# #);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:59:17
|
LL | demo4!("foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!("foo"# ##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:59:18
|
LL | demo4!("foo"###);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!("foo"## #);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:65:12
|
LL | demo2!(#"");
| ^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo2!(# "");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:68:12
|
LL | demo3!(#""#);
| ^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# ""#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:71:12
|
LL | demo3!(##"");
| ^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# #"");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:71:13
|
LL | demo3!(##"");
| ^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(## "");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:76:12
|
LL | demo2!(#"foo");
| ^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo2!(# "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:79:12
|
LL | demo3!(##"foo");
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# #"foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:79:13
|
LL | demo3!(##"foo");
| ^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(## "foo");
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:84:12
|
LL | demo3!(#"foo"#);
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo3!(# "foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:87:12
|
LL | demo4!(##"foo"#);
| ^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(# #"foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:87:13
|
LL | demo4!(##"foo"#);
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo4!(## "foo"#);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:92:12
|
LL | demo5!(##"foo"##);
| ^^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(# #"foo"##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:92:13
|
LL | demo5!(##"foo"##);
| ^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(## "foo"##);
| +
warning: will be parsed as a guarded string in Rust 2024
--> $DIR/reserved-guarded-strings-migration.rs:92:19
|
LL | demo5!(##"foo"##);
| ^^
|
= warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
= note: for more information, see issue #123735 <https://github.com/rust-lang/rust/issues/123735>
help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024
|
LL | demo5!(##"foo"# #);
| +
warning: 22 warnings emitted

View File

@ -0,0 +1,18 @@
//@ edition:2021
//@ aux-build:reserved-guarded-strings-macro-2021.rs
//@ aux-build:reserved-guarded-strings-macro-2024.rs
extern crate reserved_guarded_strings_macro_2021 as m2021;
extern crate reserved_guarded_strings_macro_2024 as m2024;
fn main() {
// Ok:
m2021::number_of_tokens_in_a_guarded_string_literal!();
m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!();
// Error, even though *this* crate is 2021:
m2024::number_of_tokens_in_a_guarded_string_literal!();
//~^ ERROR invalid string literal
m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!();
//~^ ERROR invalid string literal
}

View File

@ -0,0 +1,20 @@
error: invalid string literal
--> $DIR/reserved-guarded-strings-via-macro-2.rs:14:5
|
LL | m2024::number_of_tokens_in_a_guarded_string_literal!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
= note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: invalid string literal
--> $DIR/reserved-guarded-strings-via-macro-2.rs:16:5
|
LL | m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
= note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_unterminated_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -0,0 +1,12 @@
//@ run-pass
//@ compile-flags: -Zunstable-options
//@ edition:2024
//@ aux-build:reserved-guarded-strings-macro-2021.rs
extern crate reserved_guarded_strings_macro_2021 as m2021;
fn main() {
// Ok, even though *this* crate is 2024:
assert_eq!(m2021::number_of_tokens_in_a_guarded_string_literal!(), 3);
assert_eq!(m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!(), 2);
}

View File

@ -0,0 +1,74 @@
//@ compile-flags: -Zunstable-options
//@ edition:2024
// ignore-tidy-linelength
macro_rules! demo1 {
( $a:tt ) => { println!("one tokens") };
}
macro_rules! demo2 {
( $a:tt $b:tt ) => { println!("two tokens") };
}
macro_rules! demo3 {
( $a:tt $b:tt $c:tt ) => { println!("three tokens") };
}
macro_rules! demo4 {
( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") };
}
macro_rules! demo5 {
( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") };
}
macro_rules! demo6 {
( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") };
}
macro_rules! demo7 {
( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") };
}
macro_rules! demon {
( $($n:tt)* ) => { println!("unknown number of tokens") };
}
fn main() {
demo1!("");
demo2!(# "");
demo3!(# ""#);
demo2!(# "foo");
demo3!(# "foo"#);
demo2!("foo"#);
demo2!(blah"xx"); //~ ERROR prefix `blah` is unknown
demo2!(blah#"xx"#);
//~^ ERROR prefix `blah` is unknown
//~| ERROR invalid string literal
demo2!(## "foo"); //~ ERROR invalid string literal
demo3!("foo"###); //~ ERROR invalid string literal
demo3!(### "foo"); //~ ERROR invalid string literal
demo3!(## "foo"#); //~ ERROR invalid string literal
demo5!(### "foo"###);
//~^ ERROR invalid string literal
//~| ERROR invalid string literal
demo1!(#""); //~ ERROR invalid string literal
demo1!(#""#); //~ ERROR invalid string literal
demo1!(####""); //~ ERROR invalid string literal
demo1!(#"foo"); //~ ERROR invalid string literal
demo1!(###"foo"); //~ ERROR invalid string literal
demo1!(#"foo"#); //~ ERROR invalid string literal
demo1!(###"foo"#); //~ ERROR invalid string literal
demo1!(###"foo"##); //~ ERROR invalid string literal
demo1!(###"foo"###); //~ ERROR invalid string literal
demo2!(#"foo"###);
//~^ ERROR invalid string literal
//~| ERROR invalid string literal
// More than 255 hashes
demon!(####################################################################################################################################################################################################################################################################"foo");
//~^ ERROR invalid string literal
}

View File

@ -0,0 +1,254 @@
error: prefix `blah` is unknown
--> $DIR/reserved-guarded-strings.rs:45:12
|
LL | demo2!(blah"xx");
| ^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
LL | demo2!(blah "xx");
| +
error: prefix `blah` is unknown
--> $DIR/reserved-guarded-strings.rs:46:12
|
LL | demo2!(blah#"xx"#);
| ^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
LL | demo2!(blah #"xx"#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:46:16
|
LL | demo2!(blah#"xx"#);
| ^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo2!(blah# "xx"#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:50:12
|
LL | demo2!(## "foo");
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo2!(# # "foo");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:51:17
|
LL | demo3!("foo"###);
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo3!("foo"# ##);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:52:12
|
LL | demo3!(### "foo");
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo3!(# ## "foo");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:53:12
|
LL | demo3!(## "foo"#);
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo3!(# # "foo"#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:54:12
|
LL | demo5!(### "foo"###);
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo5!(# ## "foo"###);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:54:21
|
LL | demo5!(### "foo"###);
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo5!(### "foo"# ##);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:58:12
|
LL | demo1!(#"");
| ^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# "");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:59:12
|
LL | demo1!(#""#);
| ^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ""#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:60:12
|
LL | demo1!(####"");
| ^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ###"");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:61:12
|
LL | demo1!(#"foo");
| ^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# "foo");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:62:12
|
LL | demo1!(###"foo");
| ^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ##"foo");
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:63:12
|
LL | demo1!(#"foo"#);
| ^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# "foo"#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:64:12
|
LL | demo1!(###"foo"#);
| ^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ##"foo"#);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:65:12
|
LL | demo1!(###"foo"##);
| ^^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ##"foo"##);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:66:12
|
LL | demo1!(###"foo"###);
| ^^^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo1!(# ##"foo"###);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:67:12
|
LL | demo2!(#"foo"###);
| ^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo2!(# "foo"###);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:67:19
|
LL | demo2!(#"foo"###);
| ^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demo2!(#"foo"## #);
| +
error: invalid string literal
--> $DIR/reserved-guarded-strings.rs:72:12
|
LL | ...n!(####################################################################################################################################################################################################################################################################"foo...
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: unprefixed guarded string literals are reserved for future use since Rust 2024
help: consider inserting whitespace here
|
LL | demon!(# ###################################################################################################################################################################################################################################################################"foo");
| +
error: aborting due to 21 previous errors