Skip to content

Commit

Permalink
Improve compiler error for c-strings in pre-2021
Browse files Browse the repository at this point in the history
  • Loading branch information
chfogelman committed Dec 19, 2023
1 parent 337205e commit c6729bd
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 46 deletions.
22 changes: 8 additions & 14 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,13 +640,13 @@ impl<'a> Parser<'a> {
}
}

// Extra info for `c"str"` before 2021 edition or `c "str"` in all editions. The heuristic
// Try to detect an intended c-string literal while using a pre-2021 edition. The heuristic
// here is to identify a cooked, uninterpolated `c` id immediately followed by a string, or
// a cooked, uninterpolated `cr` id immediately followed by a string or a `#`, in an
// edition where c-string literals are not allowed. There is the slight possibility of a
// false positive for a `cr#` that wasn't intended to start a c-string literal, but the
// lexer was greedy and didn't preserve whether the `r#` on its own would have started a
// valid raw string literal.
// a cooked, uninterpolated `cr` id immediately followed by a string or a `#`, in an edition
// where c-string literals are not allowed. There is the very slight possibility of a false
// positive for a `cr#` that wasn't intended to start a c-string literal, but identifying
// that in the parser requires unbounded lookahead, so we only add a hint to the existing
// error rather than replacing it entirely.
if ((self.prev_token.kind == TokenKind::Ident(sym::c, false)
&& matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. })))
|| (self.prev_token.kind == TokenKind::Ident(sym::cr, false)
Expand All @@ -657,15 +657,9 @@ impl<'a> Parser<'a> {
&& self.prev_token.span.hi() == self.token.span.lo()
&& !self.token.span.at_least_rust_2021()
{
err.cancel();
let descr = super::token_descr(&self.token);
let mut err =
self.struct_span_err(self.token.span, format!("found unexpected token {descr}"));
err.span_label(self.token.span, "found here".to_owned());
err.note("you may be trying to declare a c-string literal");
err.note("c-string literals require edition 2021 or later");
err.note("you may be trying to write a c-string literal");
err.note("c-string literals require Rust 2021 or later");
HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
return Err(err);
}

// `pub` may be used for an item or `pub(crate)`
Expand Down
32 changes: 16 additions & 16 deletions tests/ui/editions/edition-cstr-2015-2018.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ macro_rules! construct { ($x:ident) => { $x"str" } }
//~| NOTE expected one of 8 possible tokens

macro_rules! contain { () => { c"str" } }
//~^ ERROR found unexpected token `"str"`
//~| NOTE found here
//~| NOTE you may be trying to declare a c-string literal
//~| NOTE c-string literals require edition 2021 or later
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
//~| NOTE expected one of 8 possible tokens
//~| NOTE you may be trying to write a c-string literal
//~| NOTE c-string literals require Rust 2021 or later
//~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide

Expand All @@ -25,30 +25,30 @@ fn check_macro_contain() {

fn check_basic() {
c"str";
//~^ ERROR found unexpected token `"str"`
//~| NOTE found here
//~| NOTE you may be trying to declare a c-string literal
//~| NOTE c-string literals require edition 2021 or later
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
//~| NOTE expected one of 8 possible tokens
//~| NOTE you may be trying to write a c-string literal
//~| NOTE c-string literals require Rust 2021 or later
//~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
}

fn check_craw() {
cr"str";
//~^ ERROR found unexpected token `"str"`
//~| NOTE found here
//~| NOTE you may be trying to declare a c-string literal
//~| NOTE c-string literals require edition 2021 or later
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
//~| NOTE expected one of 8 possible tokens
//~| NOTE you may be trying to write a c-string literal
//~| NOTE c-string literals require Rust 2021 or later
//~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
}

fn check_craw_hash() {
cr##"str"##;
//~^ ERROR found unexpected token `#`
//~| NOTE found here
//~| NOTE you may be trying to declare a c-string literal
//~| NOTE c-string literals require edition 2021 or later
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `#`
//~| NOTE expected one of 8 possible tokens
//~| NOTE you may be trying to write a c-string literal
//~| NOTE c-string literals require Rust 2021 or later
//~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
}
Expand Down
32 changes: 16 additions & 16 deletions tests/ui/editions/edition-cstr-2015-2018.stderr
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
error: found unexpected token `"str"`
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
--> $DIR/edition-cstr-2015-2018.rs:27:6
|
LL | c"str";
| ^^^^^ found here
| ^^^^^ expected one of 8 possible tokens
|
= note: you may be trying to declare a c-string literal
= note: c-string literals require edition 2021 or later
= note: you may be trying to write a c-string literal
= note: c-string literals require Rust 2021 or later
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide

error: found unexpected token `"str"`
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
--> $DIR/edition-cstr-2015-2018.rs:37:7
|
LL | cr"str";
| ^^^^^ found here
| ^^^^^ expected one of 8 possible tokens
|
= note: you may be trying to declare a c-string literal
= note: c-string literals require edition 2021 or later
= note: you may be trying to write a c-string literal
= note: c-string literals require Rust 2021 or later
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide

error: found unexpected token `#`
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `#`
--> $DIR/edition-cstr-2015-2018.rs:47:7
|
LL | cr##"str"##;
| ^ found here
| ^ expected one of 8 possible tokens
|
= note: you may be trying to declare a c-string literal
= note: c-string literals require edition 2021 or later
= note: you may be trying to write a c-string literal
= note: c-string literals require Rust 2021 or later
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide

Expand All @@ -48,17 +48,17 @@ LL | construct!(c);
|
= note: this error originates in the macro `construct` (in Nightly builds, run with -Z macro-backtrace for more info)

error: found unexpected token `"str"`
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"`
--> $DIR/edition-cstr-2015-2018.rs:5:33
|
LL | macro_rules! contain { () => { c"str" } }
| ^^^^^ found here
| ^^^^^ expected one of 8 possible tokens
...
LL | contain!();
| ---------- in this macro invocation
|
= note: you may be trying to declare a c-string literal
= note: c-string literals require edition 2021 or later
= note: you may be trying to write a c-string literal
= note: c-string literals require Rust 2021 or later
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
= note: this error originates in the macro `contain` (in Nightly builds, run with -Z macro-backtrace for more info)
Expand Down

0 comments on commit c6729bd

Please sign in to comment.