diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index d0604f763171b..299c4a389a36e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1561,7 +1561,31 @@ impl<'a> Parser<'a> { fn parse_expr_lit(&mut self) -> PResult<'a, Box> { let lo = self.token.span; match self.parse_opt_token_lit() { - Some((token_lit, _)) => { + Some((token_lit, span)) => { + // For raw string literals with suffixes, report the error immediately + // This helps provide better error messages for cases like r#"..."#suffix + if token_lit.suffix.is_some() + && matches!(token_lit.kind, token::StrRaw(_)) + && ast::LitKind::from_token_lit(token_lit).is_err() + { + if let Err(err) = ast::LitKind::from_token_lit(token_lit) { + let guar = report_lit_error(&self.psess, err, token_lit, span); + let token_lit = token::Lit::new(token::Err(guar), token_lit.symbol, None); + let expr = + self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit)); + + // Consume the next token if it looks like another string literal + // This prevents cascading errors when raw strings with invalid suffixes + // are immediately followed by another string + if let TokenKind::Literal(lit) = &self.token.kind { + if matches!(lit.kind, token::LitKind::Str | token::LitKind::StrRaw(_)) { + self.bump(); + } + } + + return self.maybe_recover_from_bad_qpath(expr); + } + } let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit)); self.maybe_recover_from_bad_qpath(expr) } diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index 9a51cf7096071..04fc12e1a29dd 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -10,6 +10,12 @@ error: suffixes on string literals are invalid LL | "C"suffix | ^^^^^^^^^ invalid suffix `suffix` +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:14:5 + | +LL | r#""#suffix; + | ^^^^^^^^^^^ invalid suffix `suffix` + error: suffixes on string literals are invalid --> $DIR/bad-lit-suffixes.rs:30:17 | @@ -62,12 +68,6 @@ error: suffixes on byte string literals are invalid LL | b""suffix; | ^^^^^^^^^ invalid suffix `suffix` -error: suffixes on string literals are invalid - --> $DIR/bad-lit-suffixes.rs:14:5 - | -LL | r#""#suffix; - | ^^^^^^^^^^^ invalid suffix `suffix` - error: suffixes on byte string literals are invalid --> $DIR/bad-lit-suffixes.rs:15:5 | diff --git a/tests/ui/parser/raw-string-suffix-invalid.rs b/tests/ui/parser/raw-string-suffix-invalid.rs new file mode 100644 index 0000000000000..3543d86fd7a56 --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-invalid.rs @@ -0,0 +1,6 @@ +// Test for issue #144161: Wrong error for string literal suffix when stuck together + +fn main() { + let s = r#" \\ "#r"\\ "; + //~^ ERROR suffixes on string literals are invalid +} diff --git a/tests/ui/parser/raw-string-suffix-invalid.stderr b/tests/ui/parser/raw-string-suffix-invalid.stderr new file mode 100644 index 0000000000000..84feb3342e389 --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-invalid.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/raw-string-suffix-invalid.rs:4:13 + | +LL | let s = r#" \ "#r"\ "; + | ^^^^^^^^^^ invalid suffix `r` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/raw-string-suffix-long.rs b/tests/ui/parser/raw-string-suffix-long.rs new file mode 100644 index 0000000000000..cc09933ca643d --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-long.rs @@ -0,0 +1,7 @@ +// Test for raw string literals with invalid suffixes + +fn main() { + // Raw string literal with hash delimiters and suffix + let s2 = r##"test"##suffix; + //~^ ERROR suffixes on string literals are invalid +} diff --git a/tests/ui/parser/raw-string-suffix-long.stderr b/tests/ui/parser/raw-string-suffix-long.stderr new file mode 100644 index 0000000000000..9409e0edb620a --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-long.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/raw-string-suffix-long.rs:5:14 + | +LL | let s2 = r##"test"##suffix; + | ^^^^^^^^^^^^^^^^^ invalid suffix `suffix` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/raw-string-suffix-word.rs b/tests/ui/parser/raw-string-suffix-word.rs new file mode 100644 index 0000000000000..bb2f8b19d903c --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-word.rs @@ -0,0 +1,7 @@ +// Test for raw string literal with word suffix + +fn main() { + // Raw string literal with word suffix + let s3 = r#"test"#invalid; + //~^ ERROR suffixes on string literals are invalid +} diff --git a/tests/ui/parser/raw-string-suffix-word.stderr b/tests/ui/parser/raw-string-suffix-word.stderr new file mode 100644 index 0000000000000..c6d3e539c281a --- /dev/null +++ b/tests/ui/parser/raw-string-suffix-word.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/raw-string-suffix-word.rs:5:14 + | +LL | let s3 = r#"test"#invalid; + | ^^^^^^^^^^^^^^^^ invalid suffix `invalid` + +error: aborting due to 1 previous error +