-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lexerArea: lexerArea: lexerD-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Code
fn bad_lifetime_name<'🐛>(_: &'🐛 ()) {}
Current output
error: character literal may only contain one codepoint
--> src/lib.rs:1:22
|
1 | fn bad_lifetime_name<'🐛>(_: &'🐛 ()) {}
| ^^^^^^^^^^
|
help: if you meant to write a string literal, use double quotes
|
1 - fn bad_lifetime_name<'🐛>(_: &'🐛 ()) {}
1 + fn bad_lifetime_name<"🐛>(_: &"🐛 ()) {}
|
error: unexpected closing delimiter: `)`
--> src/lib.rs:1:35
|
1 | fn bad_lifetime_name<'🐛>(_: &'🐛 ()) {}
| ^ unexpected closing delimiter
Desired output
error: a lifetime name cannot begin with a character that is neither `_` nor a `XID_Start` character
--> src/lib.rs:1:22
|
1 | fn bad_lifetime_name<'🐛>(_: &'🐛 ()) {}
| ^--
| help: `\u{1F41B}` is neither `_` nor in `XID_Start`
Rationale and extra context
See also https://doc.rust-lang.org/reference/identifiers.html.
Initially reported at #general > Compiler isn't helpful with invalid lifetimes.
Looks like this recovery path(?) is hit when starting a lifetime name (not including the '
) with a non-XID_Start
character fails both is_id_start
check and ASCII digit check hitting the !can_be_a_lifetime
codepath.
rust/compiler/rustc_lexer/src/lib.rs
Lines 824 to 842 in c79bbfa
let can_be_a_lifetime = if self.second() == '\'' { | |
// It's surely not a lifetime. | |
false | |
} else { | |
// If the first symbol is valid for identifier, it can be a lifetime. | |
// Also check if it's a number for a better error reporting (so '0 will | |
// be reported as invalid lifetime and not as unterminated char literal). | |
is_id_start(self.first()) || self.first().is_ascii_digit() | |
}; | |
if !can_be_a_lifetime { | |
let terminated = self.single_quoted_string(); | |
let suffix_start = self.pos_within_token(); | |
if terminated { | |
self.eat_literal_suffix(); | |
} | |
let kind = Char { terminated }; | |
return Literal { kind, suffix_start }; | |
} |
Other cases
Marginally related is loop labels, this complains about "unterminated character literal".
fn main() {
'🐛: {
todo!();
};
}
Rust Version
$ rustc --version --verbose
rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: aarch64-unknown-linux-gnu
release: 1.87.0
LLVM version: 20.1.1
Anything else?
No response
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lexerArea: lexerArea: lexerD-confusingDiagnostics: Confusing error or lint that should be reworked.Diagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.