Visitar URL original
Always show unsafe and display-only fixes in the CLI by ntBre · Pull Request #27810 · astral-sh/ruff · GitHub
Skip to content

Always show unsafe and display-only fixes in the CLI - #27810

Merged
ntBre merged 9 commits into
brent/0.17.0from
brent/display-only-cli
Sep 22, 2026
Merged

ntBre merged 9 commits into
brent/0.17.0from
brent/display-only-cli

Conversation

@ntBre

@ntBre ntBre commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This is the CLI accompaniment to #27807. The main change here is showing display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag like --unsafe-fixes, and I
thought it would be weird to show them unconditionally when we don't do the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes sense always to show you the
fix, and make --unsafe-fixes enable actually applying the fix. We also don't want to apply
display-only fixes, so enabling rendering of the fixes with --display-only-fixes or similar would
also disagree with the semantics of the unsafe flag. I'm open to other ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't include any additional note or warning about the fix being unsafe:

Rust diagnostics

Here's a clippy::needless_pass_by_value diagnostic, which is MaybeIncorrect ( similar to our Unsafe):

warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +

and here's a rustc LetLike diagnostic, which is has-placeholders (similar to our DisplayOnly but definitely produces invalid code in this case):

error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++

Fixes astral-sh/ty#1679

Test Plan

Updated existing snapshots, and some manual testing in the CLI:

image

Summary
--

This is the CLI accompaniment to #27807. The main change here is showing display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also don't want to apply
display-only fixes, so enabling rendering of the fixes with `--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than the note for unsafe fixes and
renders in red, as shown below.

Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

TODO
@ntBre ntBre added the cli Related to the command-line interface of Ruff or ty label Aug 17, 2026
@astral-sh-bot

astral-sh-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

Memory usage report

Memory usage unchanged ✅

@ntBre
ntBre marked this pull request as ready for review August 17, 2026 18:52
@ntBre
ntBre requested a review from a team as a code owner August 17, 2026 18:52
@astral-sh-bot
astral-sh-bot Bot requested a review from MichaReiser August 17, 2026 18:52
@ntBre ntBre added the diagnostics Diagnostic messages, annotations, fixes & rendering infra--not for PRs that just add new diagnostics label Aug 17, 2026
// analog to `--unsafe-fixes` for users to activate this or see the styling.
AnnotateLevel::ERROR,
"This is a display-only fix and is likely to be incorrect",
AnnotateLevel::ERROR.with_name("warning"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ERROR seems a bit strong to me. Nothing went wrong. I think this really just is a warning.

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.

Makes sense, I was just trying to differentiate it from the note above, which already uses the warning styling. I guess the warning vs note label is probably enough.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(as discussed offline, I agree with Micha here -- I think I'd go with AnnotateLevel::WARNING.with_name("note") here, the same as with unsafe fixes. The message is clear enough about the "risks" of blindly copying and pasting the fix)

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the change, but it's a bit unclear to me how it fits into --no-unsafe-fixes. I'm also not very familiar with that part of the CLI. Specificaly

--no-unsafe-fixes still prevents unsafe fixes from being applied and suppresses the summary hint about enabling them. But full output still shows their diffs and safety notes. Display-only suggestions remain visible too.

Without the hint, it sort of becomes confusing if we keep showing them. But that also suggests that we should only show fixes that the user has opted in to.

@ntBre

ntBre commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

I like the change, but it's a bit unclear to me how it fits into --no-unsafe-fixes. I'm also not very familiar with that part of the CLI. Specificaly

--no-unsafe-fixes still prevents unsafe fixes from being applied and suppresses the summary hint about enabling them. But full output still shows their diffs and safety notes. Display-only suggestions remain visible too.

Yeah this was all a bit unclear to me too, as I tried to summarize in the description.

Without the hint, it sort of becomes confusing if we keep showing them. But that also suggests that we should only show fixes that the user has opted in to.

This last part, "only show fixes that the user has opted in to," definitely makes sense to me and is what we currently do with --unsafe-fixes. However, I was trying to avoid adding a flag to opt in to displaying display-only fixes. By analogy to --unsafe-fixes, a flag named --display-only-fixes would imply to me both displaying and applying these fixes.

We could have something like --render-display-only-fixes, but that's getting quite cumbersome. I already personally find it a bit annoying when I have to add --unsafe-fixes to see these diffs without --fix.

I thought the simplest way of resolving all this was to:

  • always display fixes, with the accompanying note about their safety
  • make flags like --unsafe-fixes control only the application of fixes

Always displaying unsafe fixes has the same benefits we discussed for display-only fixes, namely that seeing the diff can be helpful even if you don't want to automatically apply it.

I don't feel like --no-unsafe-fixes really changes that interpretation, though I may need to check on the CLI docs. --no-unsafe-fixes is still useful to disable applying unsafe fixes you enabled somewhere else, like via unsafe-fixes in your config file.

@MichaReiser
MichaReiser self-requested a review August 19, 2026 06:09
@ntBre
ntBre marked this pull request as draft August 27, 2026 21:32
@astral-sh-bot

astral-sh-bot Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Full report with detailed diff (timing results)

@astral-sh-bot

astral-sh-bot Bot commented Sep 21, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@ntBre
ntBre marked this pull request as ready for review September 21, 2026 17:59
@ntBre
ntBre requested a review from a team as a code owner September 21, 2026 17:59
@AlexWaygood

AlexWaygood commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

The unsafe fix change here also affects ty since it has unsafe but no current display-only fixes.

out of date, we have some display-only fixes now in ty too! (I added them in the hope that we'd make a change like this 😆)

ntBre and others added 2 commits September 21, 2026 14:50
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>

@AlexWaygood AlexWaygood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is a big improvement to diagnostic rendering, I'm very much in favour of this! I think it particularly helps with some of the more complex ty diagnostics we've been adding recently, where the autofix often helps explain what the diagnostic is trying to get you to change.

To me the interaction with --no-unsafe-fixes seems intuitive as it is on this branch, and I don't think any of the docs for --no-unsafe-fixes need updating. Continuing to display unsafe fixes, but not applying them, is what I'd expect as a user with --no-unsafe-fixes, I think.

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think I agree that showing them is fine, for as long as they don't get a fix indicator.

Could you add a ty CLI test. I'm interested in the CLI output (and wording around fixes if there are only unsafe fixes)

We should also update our documentation

Ruff only enables safe fixes by default. Unsafe fixes can be enabled by settings [`unsafe-fixes`](settings.md#unsafe-fixes) in your configuration file or passing the `--unsafe-fixes` flag to `ruff check`:
and clarify what enable means (there might be other places where we need to update the documentation also)

Comment thread crates/ruff/tests/integration_test.rs Outdated
1 + # fix from stable-test-rule-display-only-fix
2 | def add_to_list(item, some_list=[]): ...
|
note: This fix may be incorrect or produce invalid syntax. It requires manual review and cannot be applied automatically

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: Should we say: This suggestion may be incorrect or produce invalid syntax. To make it clear that it isn't a safe or unsafe fix and give users a terminology to talk about these kind of fixes?

Comment thread crates/ruff/tests/integration_test.rs Outdated
1 C416 unnecessary-comprehension
Found 1 error.
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
No fixes available (1 unsafe fix can be enabled with the `--unsafe-fixes` option).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like the check output, I think it makes it clear that some fixes can be automatically applied

[*] 1 fixable with the --fix option (1 unsafe fix can be enabled with the --unsafe-fixes option).

The difference is less clear for statistics (and maybe other commands) Should we say applicable fixes. Or align the wording closer to what we use for check?

Comment thread crates/ruff/tests/integration_test.rs Outdated

Found 1 error.
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
No fixes available (1 unsafe fix can be enabled with the `--unsafe-fixes` option).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here. The wording is less clear. It seems confusing that it says that there's no fix but the diagnostic right above clearly has a fix (less confusing here with an unsafe fix, but it's less clear for a display only fix)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't find this one too bad. The fix can't be auto-applied with the current settings, but you can make it available if you pass --unsafe-fixes.

Maybe something like this would be clearer? It's a bit more verbose though

Suggested change
No fixes available (1 unsafe fix can be enabled with the `--unsafe-fixes` option).
No fixes applicable with current settings (1 unsafe fix can be enabled with the `--unsafe-fixes` option).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, this feels too long. No applicable fixes? But maybe it's fine the way it is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Codex suggests

1 unsafe fix available with --fix --unsafe-fixes.

Which I kind of like as an overall simplification

or

No safe fixes available (1 unsafe fix available with --fix --unsafe-fixes).

Which I don't like, because of safe

or

No applicable fixes (1 requires --unsafe-fixes).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I like codex's first suggestion!

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.

Sounds good, I like the short version too! There's still a longer, parenthesized version when both safe and unsafe fixes are present, but this special case seems nicer.

[*] 1 fixable with the `--fix` option (1 unsafe fix available with `--fix --unsafe-fixes`).
1 unsafe fix available with `--fix --unsafe-fixes`.

I guess this should become [*] 1 fixable with `--fix` for consistency with the --fix --unsafe-fixes part.

@ntBre
ntBre requested a review from a team as a code owner September 22, 2026 14:09
@astral-sh-bot

astral-sh-bot Bot commented Sep 22, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 98.15%. The percentage of expected errors that received a diagnostic held steady at 98.07%. The number of fully passing files held steady at 133/146.

@ntBre

ntBre commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the reviews! I've updated the messages and docs and added ty CLI tests.

@ntBre
ntBre requested a review from MichaReiser September 22, 2026 14:16
@MichaReiser

Copy link
Copy Markdown
Member

Should we put this in 0.17?

@ntBre

ntBre commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

Sure, might as well since I guess it's sort of breaking.

@ntBre
ntBre changed the base branch from main to brent/0.17.0 September 22, 2026 16:18
@ntBre ntBre added this to the v0.17 milestone Sep 22, 2026
@ntBre
ntBre merged commit 6dcb9f9 into brent/0.17.0 Sep 22, 2026
73 checks passed
@ntBre
ntBre deleted the brent/display-only-cli branch September 22, 2026 16:18
@ntBre ntBre mentioned this pull request Sep 22, 2026
2 tasks done
ntBre added a commit that referenced this pull request Sep 25, 2026
Summary
--

This is the CLI accompaniment to #27807. The main change here is showing
display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag
like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do
the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that
flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes
sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also
don't want to apply
display-only fixes, so enabling rendering of the fixes with
`--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other
ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than
the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and
display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't
include any additional note or warning about the fix being unsafe:

<details><summary>Rust diagnostics</summary>
<p>

Here's a
[`clippy::needless_pass_by_value`](https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value)
diagnostic, which is `MaybeIncorrect` ( similar to our `Unsafe`):

```
warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +
```

and here's a rustc
[`LetLike`](https://github.com/rust-lang/rust/blob/8bab26f4f68e0e26f0bb7960be334d5b520ea452/compiler/rustc_trait_selection/src/errors.rs#L268-L288)
diagnostic, which is `has-placeholders` (similar to our `DisplayOnly`
but definitely produces invalid code in this case):

```
error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++
```

</p>
</details> 

Fixes astral-sh/ty#1679


Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

<img width="965" height="400" alt="image"
src="https://github.com/user-attachments/assets/888ad79a-6853-48d4-8344-48da4af47d74"
/>

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
ntBre added a commit that referenced this pull request Sep 25, 2026
Summary
--

This is the CLI accompaniment to #27807. The main change here is showing
display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag
like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do
the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that
flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes
sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also
don't want to apply
display-only fixes, so enabling rendering of the fixes with
`--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other
ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than
the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and
display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't
include any additional note or warning about the fix being unsafe:

<details><summary>Rust diagnostics</summary>
<p>

Here's a
[`clippy::needless_pass_by_value`](https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value)
diagnostic, which is `MaybeIncorrect` ( similar to our `Unsafe`):

```
warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +
```

and here's a rustc
[`LetLike`](https://github.com/rust-lang/rust/blob/8bab26f4f68e0e26f0bb7960be334d5b520ea452/compiler/rustc_trait_selection/src/errors.rs#L268-L288)
diagnostic, which is `has-placeholders` (similar to our `DisplayOnly`
but definitely produces invalid code in this case):

```
error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++
```

</p>
</details>

Fixes astral-sh/ty#1679

Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

<img width="965" height="400" alt="image"
src="https://github.com/user-attachments/assets/888ad79a-6853-48d4-8344-48da4af47d74"
/>

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
ntBre added a commit that referenced this pull request Oct 1, 2026
Summary
--

This is the CLI accompaniment to #27807. The main change here is showing
display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag
like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do
the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that
flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes
sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also
don't want to apply
display-only fixes, so enabling rendering of the fixes with
`--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other
ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than
the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and
display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't
include any additional note or warning about the fix being unsafe:

<details><summary>Rust diagnostics</summary>
<p>

Here's a
[`clippy::needless_pass_by_value`](https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value)
diagnostic, which is `MaybeIncorrect` ( similar to our `Unsafe`):

```
warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +
```

and here's a rustc
[`LetLike`](https://github.com/rust-lang/rust/blob/8bab26f4f68e0e26f0bb7960be334d5b520ea452/compiler/rustc_trait_selection/src/errors.rs#L268-L288)
diagnostic, which is `has-placeholders` (similar to our `DisplayOnly`
but definitely produces invalid code in this case):

```
error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++
```

</p>
</details>

Fixes astral-sh/ty#1679

Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

<img width="965" height="400" alt="image"
src="https://github.com/user-attachments/assets/888ad79a-6853-48d4-8344-48da4af47d74"
/>

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
ntBre added a commit that referenced this pull request Oct 9, 2026
Summary
--

This is the CLI accompaniment to #27807. The main change here is showing
display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag
like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do
the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that
flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes
sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also
don't want to apply
display-only fixes, so enabling rendering of the fixes with
`--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other
ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than
the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and
display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't
include any additional note or warning about the fix being unsafe:

<details><summary>Rust diagnostics</summary>
<p>

Here's a
[`clippy::needless_pass_by_value`](https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value)
diagnostic, which is `MaybeIncorrect` ( similar to our `Unsafe`):

```
warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +
```

and here's a rustc
[`LetLike`](https://github.com/rust-lang/rust/blob/8bab26f4f68e0e26f0bb7960be334d5b520ea452/compiler/rustc_trait_selection/src/errors.rs#L268-L288)
diagnostic, which is `has-placeholders` (similar to our `DisplayOnly`
but definitely produces invalid code in this case):

```
error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++
```

</p>
</details>

Fixes astral-sh/ty#1679

Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

<img width="965" height="400" alt="image"
src="https://github.com/user-attachments/assets/888ad79a-6853-48d4-8344-48da4af47d74"
/>

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
ntBre added a commit that referenced this pull request Oct 9, 2026
Summary
--

This is the CLI accompaniment to #27807. The main change here is showing
display-only fix diffs in
the CLI. However, display-only fixes don't have a corresponding flag
like `--unsafe-fixes`, and I
thought it would be weird to show them unconditionally when we don't do
the same for unsafe fixes,
so this PR also unconditionally renders unsafe fix diffs, even when that
flag isn't passed. We
already emit a note about the fix being unsafe, so I think it makes
sense always to show you the
fix, and make `--unsafe-fixes` enable actually applying the fix. We also
don't want to apply
display-only fixes, so enabling rendering of the fixes with
`--display-only-fixes` or similar would
also disagree with the semantics of the unsafe flag. I'm open to other
ideas here, though.

The sub-diagnostic for display-only fixes uses a higher severity than
the note for unsafe fixes and
renders in red, as shown below.

The change here also affects ty, which now has both unsafe and
display-only fixes.

I again checked what clippy and rustc do in these cases, and they don't
include any additional note or warning about the fix being unsafe:

<details><summary>Rust diagnostics</summary>
<p>

Here's a
[`clippy::needless_pass_by_value`](https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value)
diagnostic, which is `MaybeIncorrect` ( similar to our `Unsafe`):

```
warning: this argument is passed by value, but not consumed in the function body
 --> src/main.rs:3:15
  |
3 | fn size(data: Data) -> usize {
  |               ^^^^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#needless_pass_by_value
  = note: requested on the command line with `-W clippy::needless-pass-by-value`
help: consider taking a reference instead
  |
3 | fn size(data: &Data) -> usize {
  |               +
```

and here's a rustc
[`LetLike`](https://github.com/rust-lang/rust/blob/8bab26f4f68e0e26f0bb7960be334d5b520ea452/compiler/rustc_trait_selection/src/errors.rs#L268-L288)
diagnostic, which is `has-placeholders` (similar to our `DisplayOnly`
but definitely produces invalid code in this case):

```
error[E0282]: type annotations needed for `Vec<_>`
 --> placeholder.rs:2:9
  |
2 |     let values = Vec::new();
  |         ^^^^^^   ---------- type must be known at this point
  |
help: consider giving `values` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let values: Vec<T> = Vec::new();
  |               ++++++++
```

</p>
</details>

Fixes astral-sh/ty#1679

Test Plan
--

Updated existing snapshots, and some manual testing in the CLI:

<img width="965" height="400" alt="image"
src="https://github.com/user-attachments/assets/888ad79a-6853-48d4-8344-48da4af47d74"
/>

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli Related to the command-line interface of Ruff or ty diagnostics Diagnostic messages, annotations, fixes & rendering infra--not for PRs that just add new diagnostics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show suggested unsafe fixes when rendering diagnostics on the CLI

3 participants