Skip to content

Commit 337c48c

Browse files
authored
Rollup merge of #133482 - compiler-errors:raw-lt-tick, r=estebank
Only error raw lifetime followed by `\'` in edition 2021+ Fixes #133479 cc #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`.
2 parents b574158 + d878fd8 commit 337c48c

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

compiler/rustc_lexer/src/lib.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -707,17 +707,7 @@ impl Cursor<'_> {
707707
self.bump();
708708
self.bump();
709709
self.eat_while(is_id_continue);
710-
match self.first() {
711-
'\'' => {
712-
// Check if after skipping literal contents we've met a closing
713-
// single quote (which means that user attempted to create a
714-
// string with single quotes).
715-
self.bump();
716-
let kind = Char { terminated: true };
717-
return Literal { kind, suffix_start: self.pos_within_token() };
718-
}
719-
_ => return RawLifetime,
720-
}
710+
return RawLifetime;
721711
}
722712

723713
// Either a lifetime or a character literal with

compiler/rustc_parse/src/lexer/mod.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,26 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
300300
let prefix_span = self.mk_sp(start, ident_start);
301301

302302
if prefix_span.at_least_rust_2021() {
303+
// If the raw lifetime is followed by \' then treat it a normal
304+
// lifetime followed by a \', which is to interpret it as a character
305+
// literal. In this case, it's always an invalid character literal
306+
// since the literal must necessarily have >3 characters (r#...) inside
307+
// of it, which is invalid.
308+
if self.cursor.as_str().starts_with('\'') {
309+
let lit_span = self.mk_sp(start, self.pos + BytePos(1));
310+
let contents = self.str_from_to(start + BytePos(1), self.pos);
311+
emit_unescape_error(
312+
self.dcx(),
313+
contents,
314+
lit_span,
315+
lit_span,
316+
Mode::Char,
317+
0..contents.len(),
318+
EscapeError::MoreThanOneChar,
319+
)
320+
.expect("expected error");
321+
}
322+
303323
let span = self.mk_sp(start, self.pos);
304324

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

374-
rustc_lexer::TokenKind::Unknown
375-
| rustc_lexer::TokenKind::InvalidIdent => {
394+
rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
376395
// Don't emit diagnostics for sequences of the same invalid token
377396
if swallow_next_invalid > 0 {
378397
swallow_next_invalid -= 1;

tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: character literal may only contain one codepoint
2-
--> $DIR/immediately-followed-by-lt.rs:11:4
2+
--> $DIR/immediately-followed-by-lt.rs:15:4
33
|
44
LL | w!('r#long'id);
55
| ^^^^^^^^

tests/ui/lifetimes/raw/immediately-followed-by-lt.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//@ edition: 2021
1+
//@ revisions: e2015 e2021
2+
3+
//@[e2021] edition: 2021
4+
//@[e2015] edition: 2015
5+
//@[e2015] check-pass
26

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

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

1418
fn main() {}

0 commit comments

Comments
 (0)