Change:
Given: The compiler says: This initially confused me quite a bit because I couldn't figure out why Rust wasn't seeing block comment terminator. Eventually, I realized that the line changed from being a commented out line, to starting a nested block comment. Since block comments nest in Rust, I'm used to commenting out blocks without worrying about what's inside of them which made this behaviour surprising. I'm not sure how practical it is, but it would be cool if we could check for comments like in block comments to suggest them as the source of the problem. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim
claim

Discussion:
} rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => { if !terminated { <del> let msg = match doc_style { Some(_) => "unterminated block doc-comment", None => "unterminated block comment", }; let last_bpos = self.pos; self.sess.span_diagnostic.span_fatal_with_code( self.mk_sp(start, last_bpos), msg, error_code!(E0758), ); </del> <ins> self.report_unterminated_block_comment(start, doc_style); </ins> } // Skip non-doc comments

err.emit() } <ins> fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option<DocStyle>) { let msg = match doc_style { Some(_) => "unterminated block doc-comment", None => "unterminated block comment", }; let last_bpos = self.pos; let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( self.mk_sp(start, last_bpos), msg, error_code!(E0758), ); let mut nested_block_comment_open_idxs = vec![]; let mut last_nested_block_comment_idxs = None; let mut content_chars = self.str_from(start).char_indices().peekable(); while let Some((idx, current_char)) = content_chars.next() { match content_chars.peek() { Some((_, '*')) if current_char == '/' => { nested_block_comment_open_idxs.push(idx); } Some((_, '/')) if current_char == '*' => { last_nested_block_comment_idxs = nested_block_comment_open_idxs.pop().map(|open_idx| (open_idx, idx)); } _ => {} }; } if let Some((nested_open_idx, nested_close_idx)) = last_nested_block_comment_idxs { err.span_label(self.mk_sp(start, start + BytePos(2)), msg) .span_label( self.mk_sp( start + BytePos(nested_open_idx as u32), start + BytePos(nested_open_idx as u32 + 2), ), "...as last nested comment starts here, maybe you want to close this instead?", ) .span_label( self.mk_sp( start + BytePos(nested_close_idx as u32), start + BytePos(nested_close_idx as u32 + 2), ), "...and last nested comment terminates here.", ); } err.emit(); } </ins> // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021, // using a (unknown) prefix is an error. In earlier editions, however, they // only result in a (allowed by default) lint, and are treated as regular

<ins> /* //~ ERROR E0758 /* */ /* */ </ins>

<ins> error[E0758]: unterminated block comment --> $DIR/unterminated-nested-comment.rs:1:1 | LL |   /* |   ^- |   | |  _unterminated block comment | | LL | | /* */ LL | | /* | | -- | | | | | ...as last nested comment starts here, maybe you want to close this instead? LL | | */ | |_--^ |   | |   ...and last nested comment terminates here. error: aborting due to previous error For more information about this error, try `rustc --explain E0758`. </ins>