Skip to content

Commit 982c9c1

Browse files
committed
Auto merge of rust-lang#125055 - nnethercote:Comment-FIXME, r=compiler-errors
Avoid clone in `Comments::next` `Comments::next`, in `rustc_ast_pretty`, has this comment: ``` // FIXME: This shouldn't probably clone lmao ``` The obvious thing to try is to return `Option<&Comment>` instead of `Option<Comment>`. But that leads to multiple borrows all over the place, because `Comments` must be borrowed from `PrintState` and then processed by `&mut self` methods within `PrintState`. This PR instead rearranges things so that comments are consumed as they are used, preserving the `Option<Comment>` return type without requiring any cloning. r? `@compiler-errors`
2 parents ba956ef + 74e1b46 commit 982c9c1

File tree

2 files changed

+43
-29
lines changed

2 files changed

+43
-29
lines changed

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

+37-27
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ impl PpAnn for NoAnn {}
5555

5656
pub struct Comments<'a> {
5757
sm: &'a SourceMap,
58-
comments: Vec<Comment>,
59-
current: usize,
58+
// Stored in reverse order so we can consume them by popping.
59+
reversed_comments: Vec<Comment>,
6060
}
6161

6262
/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
@@ -182,29 +182,33 @@ fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment>
182182

183183
impl<'a> Comments<'a> {
184184
pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
185-
let comments = gather_comments(sm, filename, input);
186-
Comments { sm, comments, current: 0 }
185+
let mut comments = gather_comments(sm, filename, input);
186+
comments.reverse();
187+
Comments { sm, reversed_comments: comments }
187188
}
188189

189-
// FIXME: This shouldn't probably clone lmao
190-
fn next(&self) -> Option<Comment> {
191-
self.comments.get(self.current).cloned()
190+
fn peek(&self) -> Option<&Comment> {
191+
self.reversed_comments.last()
192+
}
193+
194+
fn next(&mut self) -> Option<Comment> {
195+
self.reversed_comments.pop()
192196
}
193197

194198
fn trailing_comment(
195-
&self,
199+
&mut self,
196200
span: rustc_span::Span,
197201
next_pos: Option<BytePos>,
198202
) -> Option<Comment> {
199-
if let Some(cmnt) = self.next() {
203+
if let Some(cmnt) = self.peek() {
200204
if cmnt.style != CommentStyle::Trailing {
201205
return None;
202206
}
203207
let span_line = self.sm.lookup_char_pos(span.hi());
204208
let comment_line = self.sm.lookup_char_pos(cmnt.pos);
205209
let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
206210
if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
207-
return Some(cmnt);
211+
return Some(self.next().unwrap());
208212
}
209213
}
210214

@@ -400,7 +404,8 @@ impl std::ops::DerefMut for State<'_> {
400404

401405
/// This trait is used for both AST and HIR pretty-printing.
402406
pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
403-
fn comments(&mut self) -> &mut Option<Comments<'a>>;
407+
fn comments(&self) -> Option<&Comments<'a>>;
408+
fn comments_mut(&mut self) -> Option<&mut Comments<'a>>;
404409
fn ann_post(&mut self, ident: Ident);
405410
fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
406411

@@ -442,18 +447,18 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
442447

443448
fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
444449
let mut has_comment = false;
445-
while let Some(cmnt) = self.next_comment() {
446-
if cmnt.pos < pos {
447-
has_comment = true;
448-
self.print_comment(&cmnt);
449-
} else {
450+
while let Some(cmnt) = self.peek_comment() {
451+
if cmnt.pos >= pos {
450452
break;
451453
}
454+
has_comment = true;
455+
let cmnt = self.next_comment().unwrap();
456+
self.print_comment(cmnt);
452457
}
453458
has_comment
454459
}
455460

456-
fn print_comment(&mut self, cmnt: &Comment) {
461+
fn print_comment(&mut self, cmnt: Comment) {
457462
match cmnt.style {
458463
CommentStyle::Mixed => {
459464
if !self.is_beginning_of_line() {
@@ -517,31 +522,32 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
517522
self.hardbreak();
518523
}
519524
}
520-
if let Some(cmnts) = self.comments() {
521-
cmnts.current += 1;
522-
}
525+
}
526+
527+
fn peek_comment<'b>(&'b self) -> Option<&'b Comment> where 'a: 'b {
528+
self.comments().and_then(|c| c.peek())
523529
}
524530

525531
fn next_comment(&mut self) -> Option<Comment> {
526-
self.comments().as_mut().and_then(|c| c.next())
532+
self.comments_mut().and_then(|c| c.next())
527533
}
528534

529535
fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option<BytePos>) {
530-
if let Some(cmnts) = self.comments() {
536+
if let Some(cmnts) = self.comments_mut() {
531537
if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
532-
self.print_comment(&cmnt);
538+
self.print_comment(cmnt);
533539
}
534540
}
535541
}
536542

537543
fn print_remaining_comments(&mut self) {
538544
// If there aren't any remaining comments, then we need to manually
539545
// make sure there is a line break at the end.
540-
if self.next_comment().is_none() {
546+
if self.peek_comment().is_none() {
541547
self.hardbreak();
542548
}
543549
while let Some(cmnt) = self.next_comment() {
544-
self.print_comment(&cmnt)
550+
self.print_comment(cmnt)
545551
}
546552
}
547553

@@ -994,8 +1000,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
9941000
}
9951001

9961002
impl<'a> PrintState<'a> for State<'a> {
997-
fn comments(&mut self) -> &mut Option<Comments<'a>> {
998-
&mut self.comments
1003+
fn comments(&self) -> Option<&Comments<'a>> {
1004+
self.comments.as_ref()
1005+
}
1006+
1007+
fn comments_mut(&mut self) -> Option<&mut Comments<'a>> {
1008+
self.comments.as_mut()
9991009
}
10001010

10011011
fn ann_post(&mut self, ident: Ident) {

Diff for: compiler/rustc_hir_pretty/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,12 @@ impl std::ops::DerefMut for State<'_> {
139139
}
140140

141141
impl<'a> PrintState<'a> for State<'a> {
142-
fn comments(&mut self) -> &mut Option<Comments<'a>> {
143-
&mut self.comments
142+
fn comments(&self) -> Option<&Comments<'a>> {
143+
self.comments.as_ref()
144+
}
145+
146+
fn comments_mut(&mut self) -> Option<&mut Comments<'a>> {
147+
self.comments.as_mut()
144148
}
145149

146150
fn ann_post(&mut self, ident: Ident) {

0 commit comments

Comments
 (0)