Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect formatting when reordering module declarations #5168

Closed
edg-l opened this issue Jan 11, 2022 · 5 comments
Closed

Incorrect formatting when reordering module declarations #5168

edg-l opened this issue Jan 11, 2022 · 5 comments

Comments

@edg-l
Copy link

edg-l commented Jan 11, 2022

This:

pub mod a; // a
pub mod c; // c 
pub mod b; // b

Gets formated to:

pub mod a; // a
pub mod b;
pub mod c; // c // b

Using cargo fmt.

cargo 1.57.0 (b2e52d7ca 2021-10-21)
rustfmt 1.4.37-stable (f1edd04 2021-11-29)

found by @Patiga

@ytmimi
Copy link
Contributor

ytmimi commented Jan 13, 2022

Thanks for the report!

I can confirm that I can also reproduce the error on rustfmt 1.4.38-nightly (5056f4cf 2022-01-05).

This is a bit of a tricky one because comments aren't explicitly represented in the ast that rustfmt uses to reformat your code. Here's a high level overview of what's happening:

When going to rewrite and reorder the modules the Span starts from the start of the first module to the end of the last module. Because the trailing comments for mod a and mod c are within this span we find them easily, but we don't pick up on the trailing inline comment for mod b.

| start here
v
pub mod a; // a
pub mod c; // c 
pub mod b; // b
         ^
         | end here

Mentally You can think that rustfmt is grouping each mod with it's associated post comment (except for the last one because it's outside the span). Here's what those groups would look like:

pub mod a; // a | <-- end of item 1
pub mod c; // c | <-- end of item 2
pub mod b; | <--end of item 3 (remember we don't know about this comment because it's outside the span)

Then rustfmt reorders and writes the modules:

pub mod a; // a
pub mod b;
pub mod c; // c 

And lastly, rustfmt checks to see if there were any trailing comments that it might have missed and that's when it appends // b to the end of the now shuffled mod items because at that point there's no context that the trailing comment used to be associated with mod b.

pub mod a; // a
pub mod b;
pub mod c; // c // b

I hope that explanation of the issue helps! I've started looking into this, and I have a few ideas of how we might solve it, but I'll need a little more time to work out issues and fully test what I'm thinking!

@ytmimi
Copy link
Contributor

ytmimi commented Jan 13, 2022

In case anyone else wants to give this a go the Span I described above is located on Line 293 when calling FmtVisitor::walk_reorderable_or_regroupable_items, and what the fix will ultimately come down to is finding a reliable way to extend the span past any trailing comments.

rustfmt/src/reorder.rs

Lines 290 to 300 in 5056f4c

if at_least_one_in_file_lines && !items.is_empty() {
let lo = items.first().unwrap().span().lo();
let hi = items.last().unwrap().span().hi();
let span = mk_sp(lo, hi);
let rw = rewrite_reorderable_or_regroupable_items(
&self.get_context(),
items,
self.shape(),
span,
);
self.push_rewrite(span, rw);

@calebcartwright
Copy link
Member

calebcartwright commented Jan 13, 2022

Is this a duplicate of existing issues, e.g. #3720, #4027?

@ytmimi
Copy link
Contributor

ytmimi commented Jan 13, 2022

Yup, looks like this is a duplicate

@calebcartwright
Copy link
Member

Going to close in that case to try to avoid dialog getting split across too many issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants