Skip to content

Commit

Permalink
Rollup merge of rust-lang#133482 - compiler-errors:raw-lt-tick, r=est…
Browse files Browse the repository at this point in the history
…ebank

Only error raw lifetime followed by `\'` in edition 2021+

Fixes rust-lang#133479
cc rust-lang#132341

I think this fixes a purely theoretical regression since it only affects edition 2015 (who is using that?) and only in the very rare case of a raw lifetime followed immediately by a lifetime like `'r#a'r`.
  • Loading branch information
matthiaskrgr authored Dec 1, 2024
2 parents 4590eec + d878fd8 commit 9f7755e
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 16 deletions.
12 changes: 1 addition & 11 deletions compiler/rustc_lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -707,17 +707,7 @@ impl Cursor<'_> {
self.bump();
self.bump();
self.eat_while(is_id_continue);
match self.first() {
'\'' => {
// Check if after skipping literal contents we've met a closing
// single quote (which means that user attempted to create a
// string with single quotes).
self.bump();
let kind = Char { terminated: true };
return Literal { kind, suffix_start: self.pos_within_token() };
}
_ => return RawLifetime,
}
return RawLifetime;
}

// Either a lifetime or a character literal with
Expand Down
23 changes: 21 additions & 2 deletions compiler/rustc_parse/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,26 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
let prefix_span = self.mk_sp(start, ident_start);

if prefix_span.at_least_rust_2021() {
// If the raw lifetime is followed by \' then treat it a normal
// lifetime followed by a \', which is to interpret it as a character
// literal. In this case, it's always an invalid character literal
// since the literal must necessarily have >3 characters (r#...) inside
// of it, which is invalid.
if self.cursor.as_str().starts_with('\'') {
let lit_span = self.mk_sp(start, self.pos + BytePos(1));
let contents = self.str_from_to(start + BytePos(1), self.pos);
emit_unescape_error(
self.dcx(),
contents,
lit_span,
lit_span,
Mode::Char,
0..contents.len(),
EscapeError::MoreThanOneChar,
)
.expect("expected error");
}

let span = self.mk_sp(start, self.pos);

let lifetime_name_without_tick =
Expand Down Expand Up @@ -371,8 +391,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),

rustc_lexer::TokenKind::Unknown
| rustc_lexer::TokenKind::InvalidIdent => {
rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
// Don't emit diagnostics for sequences of the same invalid token
if swallow_next_invalid > 0 {
swallow_next_invalid -= 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: character literal may only contain one codepoint
--> $DIR/immediately-followed-by-lt.rs:11:4
--> $DIR/immediately-followed-by-lt.rs:15:4
|
LL | w!('r#long'id);
| ^^^^^^^^
Expand Down
8 changes: 6 additions & 2 deletions tests/ui/lifetimes/raw/immediately-followed-by-lt.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ edition: 2021
//@ revisions: e2015 e2021

//@[e2021] edition: 2021
//@[e2015] edition: 2015
//@[e2015] check-pass

// Make sure we reject the case where a raw lifetime is immediately followed by another
// lifetime. This reserves a modest amount of space for changing lexing to, for example,
Expand All @@ -9,6 +13,6 @@ macro_rules! w {
}

w!('r#long'id);
//~^ ERROR character literal may only contain one codepoint
//[e2021]~^ ERROR character literal may only contain one codepoint

fn main() {}

0 comments on commit 9f7755e

Please sign in to comment.