@@ -498,41 +498,48 @@ impl Cursor<'_> {
498
498
499
499
fn lifetime_or_char ( & mut self ) -> TokenKind {
500
500
debug_assert ! ( self . prev( ) == '\'' ) ;
501
- let mut starts_with_number = false ;
502
-
503
- // Check if the first symbol after '\'' is a valid identifier
504
- // character or a number (not a digit followed by '\'').
505
- if ( is_id_start ( self . nth_char ( 0 ) )
506
- || self . nth_char ( 0 ) . is_digit ( 10 ) && {
507
- starts_with_number = true ;
508
- true
509
- } )
510
- && self . nth_char ( 1 ) != '\''
511
- {
512
- self . bump ( ) ;
513
501
514
- // Skip the identifier.
515
- while is_id_continue ( self . nth_char ( 0 ) ) {
516
- self . bump ( ) ;
517
- }
502
+ let can_be_a_lifetime = if self . second ( ) == '\'' {
503
+ // It's surely not a lifetime.
504
+ false
505
+ } else {
506
+ // If the first symbol is valid for identifier, it can be a lifetime.
507
+ // Also check if it's a number for a better error reporting (so '0 will
508
+ // be reported as invalid lifetime and not as unterminated char literal).
509
+ is_id_start ( self . first ( ) ) || self . first ( ) . is_digit ( 10 )
510
+ } ;
518
511
519
- return if self . nth_char ( 0 ) == '\'' {
520
- self . bump ( ) ;
521
- let kind = Char { terminated : true } ;
522
- Literal { kind, suffix_start : self . len_consumed ( ) }
523
- } else {
524
- Lifetime { starts_with_number }
525
- } ;
512
+ if !can_be_a_lifetime {
513
+ let terminated = self . single_quoted_string ( ) ;
514
+ let suffix_start = self . len_consumed ( ) ;
515
+ if terminated {
516
+ self . eat_literal_suffix ( ) ;
517
+ }
518
+ let kind = Char { terminated } ;
519
+ return Literal { kind, suffix_start } ;
526
520
}
527
521
528
- // This is not a lifetime (checked above), parse a char literal.
529
- let terminated = self . single_quoted_string ( ) ;
530
- let suffix_start = self . len_consumed ( ) ;
531
- if terminated {
532
- self . eat_literal_suffix ( ) ;
522
+ // Either a lifetime or a character literal with
523
+ // length greater than 1.
524
+
525
+ let starts_with_number = self . first ( ) . is_digit ( 10 ) ;
526
+
527
+ // Skip the literal contents.
528
+ // First symbol can be a number (which isn't a valid identifier start),
529
+ // so skip it without any checks.
530
+ self . bump ( ) ;
531
+ self . eat_while ( is_id_continue) ;
532
+
533
+ // Check if after skipping literal contents we've met a closing
534
+ // single quote (which means that user attempted to create a
535
+ // string with single quotes).
536
+ if self . first ( ) == '\'' {
537
+ self . bump ( ) ;
538
+ let kind = Char { terminated : true } ;
539
+ return Literal { kind, suffix_start : self . len_consumed ( ) } ;
533
540
}
534
- let kind = Char { terminated } ;
535
- return Literal { kind , suffix_start } ;
541
+
542
+ return Lifetime { starts_with_number } ;
536
543
}
537
544
538
545
fn single_quoted_string ( & mut self ) -> bool {
0 commit comments