Skip to content

Commit 77031f3

Browse files
authored
Rollup merge of #96355 - estebank:issue-95030, r=compiler-errors
Better handle too many `#` recovery in raw str Point at all the unnecessary trailing `#`. Better handle interaction with outer attributes when `;` is missing. Fix #95030.
2 parents 2381897 + 3587406 commit 77031f3

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+34-9
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,11 @@ impl<'a> Parser<'a> {
431431
return Ok(true);
432432
} else if self.look_ahead(0, |t| {
433433
t == &token::CloseDelim(token::Brace)
434-
|| (
435-
t.can_begin_expr() && t != &token::Semi && t != &token::Pound
436-
// Avoid triggering with too many trailing `#` in raw string.
437-
)
434+
|| (t.can_begin_expr() && t != &token::Semi && t != &token::Pound)
435+
// Avoid triggering with too many trailing `#` in raw string.
436+
|| (sm.is_multiline(
437+
self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo())
438+
) && t == &token::Pound)
438439
}) {
439440
// Missing semicolon typo. This is triggered if the next token could either start a
440441
// new statement or is a block close. For example:
@@ -508,7 +509,12 @@ impl<'a> Parser<'a> {
508509
}
509510

510511
if self.check_too_many_raw_str_terminators(&mut err) {
511-
return Err(err);
512+
if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
513+
err.emit();
514+
return Ok(true);
515+
} else {
516+
return Err(err);
517+
}
512518
}
513519

514520
if self.prev_token.span == DUMMY_SP {
@@ -538,22 +544,41 @@ impl<'a> Parser<'a> {
538544
}
539545

540546
fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
547+
let sm = self.sess.source_map();
541548
match (&self.prev_token.kind, &self.token.kind) {
542549
(
543550
TokenKind::Literal(Lit {
544551
kind: LitKind::StrRaw(n_hashes) | LitKind::ByteStrRaw(n_hashes),
545552
..
546553
}),
547554
TokenKind::Pound,
548-
) => {
555+
) if !sm.is_multiline(
556+
self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
557+
) =>
558+
{
559+
let n_hashes: u8 = *n_hashes;
549560
err.set_primary_message("too many `#` when terminating raw string");
561+
let str_span = self.prev_token.span;
562+
let mut span = self.token.span;
563+
let mut count = 0;
564+
while self.token.kind == TokenKind::Pound
565+
&& !sm.is_multiline(span.shrink_to_hi().until(self.token.span.shrink_to_lo()))
566+
{
567+
span = span.with_hi(self.token.span.hi());
568+
self.bump();
569+
count += 1;
570+
}
571+
err.set_span(span);
550572
err.span_suggestion(
551-
self.token.span,
552-
"remove the extra `#`",
573+
span,
574+
&format!("remove the extra `#`{}", pluralize!(count)),
553575
String::new(),
554576
Applicability::MachineApplicable,
555577
);
556-
err.note(&format!("the raw string started with {n_hashes} `#`s"));
578+
err.span_label(
579+
str_span,
580+
&format!("this raw string started with {n_hashes} `#`{}", pluralize!(n_hashes)),
581+
);
557582
true
558583
}
559584
_ => false,
+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
static s: &'static str =
2+
r#""## //~ ERROR too many `#` when terminating raw string
3+
;
4+
5+
static s2: &'static str =
26
r#"
3-
"## //~ too many `#` when terminating raw string
7+
"#### //~ ERROR too many `#` when terminating raw string
48
;
9+
10+
const A: &'static str = r"" //~ ERROR expected `;`, found `#`
11+
12+
// Test
13+
#[test]
14+
fn test() {}
15+
16+
const B: &'static str = r""## //~ ERROR too many `#` when terminating raw string
17+
18+
// Test
19+
#[test]
20+
fn test2() {}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,36 @@
11
error: too many `#` when terminating raw string
2-
--> $DIR/raw-str-unbalanced.rs:3:9
2+
--> $DIR/raw-str-unbalanced.rs:2:10
33
|
4-
LL | "##
5-
| ^ help: remove the extra `#`
4+
LL | r#""##
5+
| -----^ help: remove the extra `#`
6+
| |
7+
| this raw string started with 1 `#`
8+
9+
error: too many `#` when terminating raw string
10+
--> $DIR/raw-str-unbalanced.rs:7:9
11+
|
12+
LL | / r#"
13+
LL | | "####
14+
| | -^^^ help: remove the extra `#`s
15+
| |________|
16+
| this raw string started with 1 `#`
17+
18+
error: expected `;`, found `#`
19+
--> $DIR/raw-str-unbalanced.rs:10:28
20+
|
21+
LL | const A: &'static str = r""
22+
| ^ help: add `;` here
23+
...
24+
LL | #[test]
25+
| - unexpected token
26+
27+
error: too many `#` when terminating raw string
28+
--> $DIR/raw-str-unbalanced.rs:16:28
629
|
7-
= note: the raw string started with 1 `#`s
30+
LL | const B: &'static str = r""##
31+
| ---^^ help: remove the extra `#`s
32+
| |
33+
| this raw string started with 0 `#`s
834

9-
error: aborting due to previous error
35+
error: aborting due to 4 previous errors
1036

0 commit comments

Comments
 (0)