Skip to content

Fix skip range miscalculation - #7049

Open
matthewhughes934 wants to merge 2 commits into
rust-lang:mainfrom
matthewhughes934:fix-skips-pre-work
Open

Fix skip range miscalculation#7049
matthewhughes934 wants to merge 2 commits into
rust-lang:mainfrom
matthewhughes934:fix-skips-pre-work

Conversation

@matthewhughes934

Copy link
Copy Markdown
Contributor

As well as a bit of code tidying

  • Idempotent test: avoid redundant file reads

    We read the 'significant comments' in check_files, so just pass it
    down rather than re-reading the test file.

  • Fix skip range miscalculated on nested blocks

    Fix a bug in FmtVisitor::push_skipped_with_span that assumed
    line_number was always absolute (within a given file) and instead set
    the end of the range to be the end of the span with the skip attribute.

    Found while investigating issue rustfmt::skip sometimes ignored when using error_on_line_overflow and error_on_unformatted #6954 (but this commit doesn't address
    that issue).

We read the 'significant comments' in `check_files`, so just pass it
down rather than re-reading the test file.
Fix a bug in `FmtVisitor::push_skipped_with_span` that assumed
`line_number` was always absolute (within a given file) and instead set
the end of the range to be the end of the span with the skip attribute.

Found while investigating issue rust-lang#6954 (but this commit doesn't address
that issue).
@rustbot rustbot added the S-waiting-on-review Status: awaiting review from the assignee but also interested parties. label Aug 22, 2026
Comment thread src/visitor.rs
Comment on lines 809 to 813
let lo = std::cmp::min(attrs_end + 1, first_line);
self.push_rewrite_inner(item_span, None);
let hi = self.line_number + 1;
let hi = self.psess.line_of_byte_pos(item_span.hi());
self.skipped_range.borrow_mut().push((lo, hi));
}

@ytmimi ytmimi Aug 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've wondered for a while if using the spans from the source makes sense when it comes to determining the skipped_range. Wouldn't we have to figure out the range relative to what's already been formatted in the file?

For example:

fn main() {
   let some.long().method().call().chain().that().will().wrap();

   #[rustfmt::skip] // line 4 before formatting;
   let x = 100;
}
fn main() {
   let some
        .long()
        .method()
        .call()
        .chain()
        .that()
        .will()
        .wrap();

   #[rustfmt::skip] // line 11 after formatting;
   let x = 100;
}

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't we have to figure out the range relative to what's already been formatted in the file?

yes 🙃, I can break my test with your change: on the first run it adds a 'skip' range that ends before the long string after formatting the method chain (no errors on subsequent runs, once the chain is formatted)

diff --git i/tests/target/skip_with_overflow.rs w/tests/target/skip_with_overflow.rs
index a3a03b80..89cd7a3e 100644
--- i/tests/target/skip_with_overflow.rs
+++ w/tests/target/skip_with_overflow.rs
@@ -12,8 +12,10 @@ fn foo() {
         // the bug: we'd mark the region (lo=16, hi=10) as skipped
         // the lo value is correct, but the hi value is the offset of the line after the end of the
         // 'if' block relative to the start of the '|| {' block
-        #[rustfmt::skip]
         if true {
+            some.very().very().very().very().very().very().long().method().call().chain().that().will().wrap();
+
+            #[rustfmt::skip]
             println!(
                 "this is a very long string, it goes over max_width. This is just padding to push it over"
             );

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which leaves me with the question: do we fix the bug in the current approach (writing skips w.r.t unformatted source). Or, do we try and move to some more robust approach? I have no idea how the latter would look, some ideas that come to mind (I have not thought about them much, neither of them feel very good):

  • checking for overflows on each line we push (where we have the context of the current span we're working on)
  • Append some marker comment like // _RUSTFMT_SKIP_HERE to all lines in a skip block, so when looking at the formatted source we know what's skip (then strip out those comments before writing things out)

@ytmimi ytmimi Aug 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make more sense to turn this into a snapshot test and show that stderr is empty. Alternatively you can write a unit test like this one.

View changes since the review

@ytmimi

ytmimi commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: awaiting review from the assignee but also interested parties. labels Aug 24, 2026
@rustbot

rustbot commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

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

Labels

S-waiting-on-author Status: awaiting some action (such as code changes or more information) from the author.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants