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

Suggest using deref in patterns #132939

Merged
merged 1 commit into from
Dec 15, 2024
Merged

Conversation

uellenberg
Copy link
Contributor

@uellenberg uellenberg commented Nov 12, 2024

Fixes #132784

This changes the following code:

use std::sync::Arc;
fn main() {
    let mut x = Arc::new(Some(1));
    match x {
        Some(_) => {}
        None => {}
    }
}

to output

error[E0308]: mismatched types
  --> src/main.rs:5:9
   |
LL |     match x {
   |           - this expression has type `Arc<Option<{integer}>>`
...
LL |         Some(_) => {}
   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
   |
   = note: expected struct `Arc<Option<{integer}>>`
                found enum `Option<_>`
help: consider dereferencing to access the inner value using the Deref trait
   |
LL |     match *x {
   |           ~~

instead of

error[E0308]: mismatched types
 --> src/main.rs:5:9
  |
4 |     match x {
  |           - this expression has type `Arc<Option<{integer}>>`
5 |         Some(_) => {}
  |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
  |
  = note: expected struct `Arc<Option<{integer}>>`
               found enum `Option<_>`

This makes it more obvious that a Deref is available, and gives a suggestion on how to use it in order to fix the issue at hand.

@rustbot
Copy link
Collaborator

rustbot commented Nov 12, 2024

r? @BoxyUwU

rustbot has assigned @BoxyUwU.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 12, 2024
@@ -359,15 +369,35 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
&& ty.boxed_ty() == Some(found)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
&& let Ok(mut snippet) = self.tcx.sess.source_map().span_to_snippet(span)
Copy link
Member

Choose a reason for hiding this comment

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

I know it's preexisting, but this snippet logic is unnecessary. You should be able to just give a suggestion like "*" that is inserted before the match scrutinee with span.shrink_to_lo().

Copy link
Member

Choose a reason for hiding this comment

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

It may also look better if you change this into a "verbose" suggestion with span_suggestion_verbose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've gone back on this, because I'm not sure how to override a span in a suggestion using multipart. Please let me know if there's a way to do so.

@rust-log-analyzer

This comment has been minimized.

@uellenberg
Copy link
Contributor Author

I haven't gone through the tests yet, because there are still some problems that I haven't figured out yet. The logic for adding references still has to be redone, but that will come with solving the other issues.

First, I'm still not happy about the suggestion given above. I may just add a check for the simple case of having a reference, since I think that covers the majority of times it'll appear.

A bigger issue is that, when rustfix tries to apply the suggestions, it does so for each part of the match arm. For example, tests/ui/issues/issue-57741-dereference-boxed-value/issue-57741.rs fixes to **x, even though each suggestion only says to use *x. I can add a check for the arm index, but that happens really far up in the call hierarchy. Is there a better way?

@rust-log-analyzer

This comment has been minimized.

@uellenberg uellenberg force-pushed the suggest-deref branch 2 times, most recently from 5fb18a6 to d2e4358 Compare November 12, 2024 22:47
@uellenberg
Copy link
Contributor Author

The issues I mentioned above have been resolved.

@uellenberg
Copy link
Contributor Author

I can also expand the suggestion to specify which Deref impls are being used to get from type A to B.

@uellenberg
Copy link
Contributor Author

r? rust-lang/diagnostics

@rustbot rustbot assigned oli-obk and unassigned compiler-errors Dec 6, 2024
compiler/rustc_hir_typeck/src/pat.rs Outdated Show resolved Hide resolved
compiler/rustc_hir_typeck/src/pat.rs Outdated Show resolved Hide resolved
&& ty.boxed_ty() == Some(found)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
&& let Ok(mut peeled_snippet) =
self.tcx.sess.source_map().span_to_snippet(origin_expr.peeled_span)
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using a snippet, you can track a prefix and an optional postfix suggestion. This way you can build the multipart suggestion right when you need it while being able to modify the prefix as you need to

Copy link
Contributor Author

@uellenberg uellenberg Dec 13, 2024

Choose a reason for hiding this comment

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

I haven't been able to implement this without rustfix applying the suggestion twice. Box deref suggestion's MachineApplicability could be downgraded, but that seems worse.

Relevant zulip: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/Rustfix.20applying.20multipart.20suggestion.20twice

@rustbot rustbot added S-waiting-on-author Status: This is 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 Dec 9, 2024
@uellenberg
Copy link
Contributor Author

@rustbot review

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 13, 2024
@oli-obk
Copy link
Contributor

oli-obk commented Dec 14, 2024

Thanks for the thorough investigation. I think we'll need to adjust rustfix to also consider suggestion spans as overlapping if they touch

@bors r+

@bors
Copy link
Contributor

bors commented Dec 14, 2024

📌 Commit 831f454 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 14, 2024
@oli-obk oli-obk self-requested a review December 14, 2024 14:43
Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

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

Whoops, clicked review request instead of dismiss on mobile by accident

bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 15, 2024
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#132939 (Suggest using deref in patterns)
 - rust-lang#133293 (Updates Solaris target information, adds Solaris maintainer)
 - rust-lang#133392 (Fix ICE when multiple supertrait substitutions need assoc but only one is provided)
 - rust-lang#133986 (Add documentation for anonymous pipe module)
 - rust-lang#134022 (Doc: Extend for tuples to be stabilized in 1.85.0)
 - rust-lang#134259 (Clean up `infer_return_ty_for_fn_sig`)
 - rust-lang#134264 (Arbitrary self types v2: Weak & NonNull diagnostics)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit db77788 into rust-lang:master Dec 15, 2024
6 checks passed
@rustbot rustbot added this to the 1.85.0 milestone Dec 15, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Dec 15, 2024
Rollup merge of rust-lang#132939 - uellenberg:suggest-deref, r=oli-obk

Suggest using deref in patterns

Fixes rust-lang#132784

This changes the following code:
```rs
use std::sync::Arc;
fn main() {
    let mut x = Arc::new(Some(1));
    match x {
        Some(_) => {}
        None => {}
    }
}
```

to output
```rs
error[E0308]: mismatched types
  --> src/main.rs:5:9
   |
LL |     match x {
   |           - this expression has type `Arc<Option<{integer}>>`
...
LL |         Some(_) => {}
   |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
   |
   = note: expected struct `Arc<Option<{integer}>>`
                found enum `Option<_>`
help: consider dereferencing to access the inner value using the Deref trait
   |
LL |     match *x {
   |           ~~
```

instead of
```rs
error[E0308]: mismatched types
 --> src/main.rs:5:9
  |
4 |     match x {
  |           - this expression has type `Arc<Option<{integer}>>`
5 |         Some(_) => {}
  |         ^^^^^^^ expected `Arc<Option<{integer}>>`, found `Option<_>`
  |
  = note: expected struct `Arc<Option<{integer}>>`
               found enum `Option<_>`
```

This makes it more obvious that a Deref is available, and gives a suggestion on how to use it in order to fix the issue at hand.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggest &* when appropriate
7 participants