Skip to content

Conversation

BurntSushi
Copy link
Member

@BurntSushi BurntSushi commented Jun 26, 2025

It turns out that annotate-snippets doesn't do a great job of
consistently handling tabs. The intent of the implementation is clearly
to expand tabs into 4 ASCII whitespace characters. But there are a few
places where the column computation wasn't taking this expansion into
account. In particular, the unicode-width crate returns None for a
\t input, and annotate-snippets would in turn treat this as either
zero columns or one column. Both are wrong.

In patching this, it caused one of the existing annotate-snippets
tests to fail. I spent a fair bit of time on it trying to fix it before
coming to the conclusion that the test itself was wrong. In particular,
the annotation ranges are 4 bytes off. However, when the range was
wrong, the buggy code was rendering the example as intended since
\t characters were treated as taking up zero columns of space. Now
that they are correctly computed as taking up 4 columns of space, the
offsets of the test needed to be adjusted.

Fixes astral-sh/ty#670

This converts the MRE in #670 into a fixture test for
`annotate-snippets`.
It turns out that `annotate-snippets` doesn't do a great job of
consistently handling tabs. The intent of the implementation is clearly
to expand tabs into 4 ASCII whitespace characters. But there are a few
places where the column computation wasn't taking this expansion into
account. In particular, the `unicode-width` crate returns `None` for a
`\t` input, and `annotate-snippets` would in turn treat this as either
zero columns or one column. Both are wrong.

In patching this, it caused one of the existing `annotate-snippets`
tests to fail. I spent a fair bit of time on it trying to fix it before
coming to the conclusion that the test itself was wrong. In particular,
the annotation ranges are 4 bytes off. However, when the range was
wrong, the buggy code was rendering the example as intended since `\t`
characters were treated as taking up zero columns of space. Now that
they are correctly computed as taking up 4 columns of space, the offsets
of the test needed to be adjusted.

Fixes #670
@BurntSushi BurntSushi requested a review from MichaReiser June 26, 2025 14:56
@BurntSushi BurntSushi added bug Something isn't working ty Multi-file analysis & type inference diagnostics Related to reporting of diagnostics. labels Jun 26, 2025
@MichaReiser
Copy link
Member

In particular, the unicode-width crate returns None for a \t input

That's a somewhat "recent" change in unicode-width, I think it used to return 1. So maybe that used to work

@MichaReiser
Copy link
Member

Uff, that sounds awful to debug. Thanks for tracking this down

Copy link
Contributor

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@BurntSushi
Copy link
Member Author

In particular, the unicode-width crate returns None for a \t input

That's a somewhat "recent" change in unicode-width, I think it used to return 1. So maybe that used to work

I think this was for \n, not \t: unicode-rs/unicode-width#60

@BurntSushi BurntSushi merged commit 76619b9 into main Jun 26, 2025
38 checks passed
@BurntSushi BurntSushi deleted the ag/fix-diagnostic-rendering-panic branch June 26, 2025 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working diagnostics Related to reporting of diagnostics. ty Multi-file analysis & type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Panic attempt to subtract with overflow in crates/ruff_annotate_snippets/src/renderer/margin.rs:74:16
2 participants