@@ -431,10 +431,11 @@ impl<'a> Parser<'a> {
431431 return Ok ( true ) ;
432432 } else if self . look_ahead ( 0 , |t| {
433433 t == & token:: CloseDelim ( token:: Brace )
434- || (
435- t. can_begin_expr ( ) && t != & token:: Semi && t != & token:: Pound
436- // Avoid triggering with too many trailing `#` in raw string.
437- )
434+ || ( t. can_begin_expr ( ) && t != & token:: Semi && t != & token:: Pound )
435+ // Avoid triggering with too many trailing `#` in raw string.
436+ || ( sm. is_multiline (
437+ self . prev_token . span . shrink_to_hi ( ) . until ( self . token . span . shrink_to_lo ( ) )
438+ ) && t == & token:: Pound )
438439 } ) {
439440 // Missing semicolon typo. This is triggered if the next token could either start a
440441 // new statement or is a block close. For example:
@@ -508,7 +509,12 @@ impl<'a> Parser<'a> {
508509 }
509510
510511 if self . check_too_many_raw_str_terminators ( & mut err) {
511- return Err ( err) ;
512+ if expected. contains ( & TokenType :: Token ( token:: Semi ) ) && self . eat ( & token:: Semi ) {
513+ err. emit ( ) ;
514+ return Ok ( true ) ;
515+ } else {
516+ return Err ( err) ;
517+ }
512518 }
513519
514520 if self . prev_token . span == DUMMY_SP {
@@ -538,22 +544,41 @@ impl<'a> Parser<'a> {
538544 }
539545
540546 fn check_too_many_raw_str_terminators ( & mut self , err : & mut Diagnostic ) -> bool {
547+ let sm = self . sess . source_map ( ) ;
541548 match ( & self . prev_token . kind , & self . token . kind ) {
542549 (
543550 TokenKind :: Literal ( Lit {
544551 kind : LitKind :: StrRaw ( n_hashes) | LitKind :: ByteStrRaw ( n_hashes) ,
545552 ..
546553 } ) ,
547554 TokenKind :: Pound ,
548- ) => {
555+ ) if !sm. is_multiline (
556+ self . prev_token . span . shrink_to_hi ( ) . until ( self . token . span . shrink_to_lo ( ) ) ,
557+ ) =>
558+ {
559+ let n_hashes: u8 = * n_hashes;
549560 err. set_primary_message ( "too many `#` when terminating raw string" ) ;
561+ let str_span = self . prev_token . span ;
562+ let mut span = self . token . span ;
563+ let mut count = 0 ;
564+ while self . token . kind == TokenKind :: Pound
565+ && !sm. is_multiline ( span. shrink_to_hi ( ) . until ( self . token . span . shrink_to_lo ( ) ) )
566+ {
567+ span = span. with_hi ( self . token . span . hi ( ) ) ;
568+ self . bump ( ) ;
569+ count += 1 ;
570+ }
571+ err. set_span ( span) ;
550572 err. span_suggestion (
551- self . token . span ,
552- "remove the extra `#`" ,
573+ span,
574+ & format ! ( "remove the extra `#`{}" , pluralize! ( count ) ) ,
553575 String :: new ( ) ,
554576 Applicability :: MachineApplicable ,
555577 ) ;
556- err. note ( & format ! ( "the raw string started with {n_hashes} `#`s" ) ) ;
578+ err. span_label (
579+ str_span,
580+ & format ! ( "this raw string started with {n_hashes} `#`{}" , pluralize!( n_hashes) ) ,
581+ ) ;
557582 true
558583 }
559584 _ => false ,
0 commit comments