@@ -498,41 +498,48 @@ impl Cursor<'_> {
498498
499499 fn lifetime_or_char ( & mut self ) -> TokenKind {
500500 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 ( ) ;
513501
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+ } ;
518511
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 } ;
526520 }
527521
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 ( ) } ;
533540 }
534- let kind = Char { terminated } ;
535- return Literal { kind , suffix_start } ;
541+
542+ return Lifetime { starts_with_number } ;
536543 }
537544
538545 fn single_quoted_string ( & mut self ) -> bool {
0 commit comments