@@ -182,16 +182,7 @@ impl<'a> StringReader<'a> {
182182 }
183183 rustc_lexer:: TokenKind :: BlockComment { doc_style, terminated } => {
184184 if !terminated {
185- let msg = match doc_style {
186- Some ( _) => "unterminated block doc-comment" ,
187- None => "unterminated block comment" ,
188- } ;
189- let last_bpos = self . pos ;
190- self . sess . span_diagnostic . span_fatal_with_code (
191- self . mk_sp ( start, last_bpos) ,
192- msg,
193- error_code ! ( E0758 ) ,
194- ) ;
185+ self . report_unterminated_block_comment ( start, doc_style) ;
195186 }
196187
197188 // Skip non-doc comments
@@ -553,6 +544,55 @@ impl<'a> StringReader<'a> {
553544 err. emit ( )
554545 }
555546
547+ fn report_unterminated_block_comment ( & self , start : BytePos , doc_style : Option < DocStyle > ) {
548+ let msg = match doc_style {
549+ Some ( _) => "unterminated block doc-comment" ,
550+ None => "unterminated block comment" ,
551+ } ;
552+ let last_bpos = self . pos ;
553+ let mut err = self . sess . span_diagnostic . struct_span_fatal_with_code (
554+ self . mk_sp ( start, last_bpos) ,
555+ msg,
556+ error_code ! ( E0758 ) ,
557+ ) ;
558+ let mut nested_block_comment_open_idxs = vec ! [ ] ;
559+ let mut last_nested_block_comment_idxs = None ;
560+ let mut content_chars = self . str_from ( start) . char_indices ( ) . peekable ( ) ;
561+
562+ while let Some ( ( idx, current_char) ) = content_chars. next ( ) {
563+ match content_chars. peek ( ) {
564+ Some ( ( _, '*' ) ) if current_char == '/' => {
565+ nested_block_comment_open_idxs. push ( idx) ;
566+ }
567+ Some ( ( _, '/' ) ) if current_char == '*' => {
568+ last_nested_block_comment_idxs =
569+ nested_block_comment_open_idxs. pop ( ) . map ( |open_idx| ( open_idx, idx) ) ;
570+ }
571+ _ => { }
572+ } ;
573+ }
574+
575+ if let Some ( ( nested_open_idx, nested_close_idx) ) = last_nested_block_comment_idxs {
576+ err. span_label ( self . mk_sp ( start, start + BytePos ( 2 ) ) , msg)
577+ . span_label (
578+ self . mk_sp (
579+ start + BytePos ( nested_open_idx as u32 ) ,
580+ start + BytePos ( nested_open_idx as u32 + 2 ) ,
581+ ) ,
582+ "...as last nested comment starts here, maybe you want to close this instead?" ,
583+ )
584+ . span_label (
585+ self . mk_sp (
586+ start + BytePos ( nested_close_idx as u32 ) ,
587+ start + BytePos ( nested_close_idx as u32 + 2 ) ,
588+ ) ,
589+ "...and last nested comment terminates here." ,
590+ ) ;
591+ }
592+
593+ err. emit ( ) ;
594+ }
595+
556596 // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
557597 // using a (unknown) prefix is an error. In earlier editions, however, they
558598 // only result in a (allowed by default) lint, and are treated as regular
0 commit comments