Skip to content

improve diagnostic for raw pointer field access with -> #139921

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

Merged
merged 1 commit into from
Apr 23, 2025

Conversation

Kivooeo
Copy link
Contributor

@Kivooeo Kivooeo commented Apr 16, 2025

This PR enhances the error messages emitted by the Rust compiler when users attempt to use the -> operator for field access on raw pointers or when dereferencing is needed. The changes aim to provide clearer guidance, by suggesting the correct use of the . operator and explicit dereferencing.

Before:

help: `xs` is a raw pointer; try dereferencing it
   |
LL |         (*xs)->count += 1;
   |         ++  +

Now:

help: use `.` on a dereferenced raw pointer instead
   |
LL -         xs->count += 1;
LL +         (*xs).count += 1;
   |

I added extra clarification in the message. Since this error occurs in the parser, we can't be certain that the type is a raw pointer. That's why the message includes only a small note in brackets. (In contrast, the message above is emitted in HIR, where we can check whether it's a raw pointer.)

Before:

  --> main.rs:11:11
   |
11 |         xs->count += 1;
   |           ^^
   |
   = help: the . operator will dereference the value if needed

After:

--> main.rs:11:11
   |
11 |         xs->count += 1;
   |           ^^
   |
   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer

@rustbot
Copy link
Collaborator

rustbot commented Apr 16, 2025

r? @estebank

rustbot has assigned @estebank.
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 Apr 16, 2025
Applicability::MaybeIncorrect,
let full_span = base.span.to(field.span);

let base_snippet = self
Copy link
Member

@fmease fmease Apr 16, 2025

Choose a reason for hiding this comment

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

Instead of using span_to_snippet (best to be avoided if possible) just to use it verbatim in the suggestion, you can use a multi-part suggestion (multipart_suggestion_verbose).

The argument to this method should probably look something like

vec![
    (base.span.shrink_to_lo(), "(*".into()),
    (base.span.to(field.span.shrink_to_lo()), format!(").{}", field.name)),
]

I haven't verified these spans, you might need to play around a bit.

You could actually make this a three-part suggestion, not just a two-part one.

Copy link
Contributor Author

@Kivooeo Kivooeo Apr 16, 2025

Choose a reason for hiding this comment

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

Yeah, I tried this thing as one of first my attemps to make it work

    let suggestion = vec![
        (base.span.shrink_to_lo(), "(*".to_string()),
        (base.span.shrink_to_hi(), format!(").{}", field.name)),
    ];

But this didn't work for me because it gives
(*xs).count->count += 1;
So I gave up and went this way you can see in PR, I surely will play around it a little more.
But I have also new question, how do i generate new stderr files? Because CI failing on comparing them because I didn't change them

Copy link
Member

Choose a reason for hiding this comment

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

--bless

Copy link
Member

Choose a reason for hiding this comment

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

@rust-log-analyzer

This comment has been minimized.

@compiler-errors
Copy link
Member

Please squash the last commit into the first

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2025
@rustbot

This comment has been minimized.

@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2025
@@ -248,7 +248,7 @@ parse_expected_trait_in_trait_impl_found_type = expected a trait, found type

parse_expr_rarrow_call = `->` used for field access or method call
.suggestion = try using `.` instead
.help = the `.` operator will dereference the value if needed
.help = the `.` operator will dereference the value if needed (if value is raw pointer you have to derefernce it by yourself)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.help = the `.` operator will dereference the value if needed (if value is raw pointer you have to derefernce it by yourself)
.help = the `.` operator will dereference the value if needed (if value is a raw pointer you have to dereference it by yourself)

Copy link
Contributor

Choose a reason for hiding this comment

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

Anyhow, I'm not a fan of this phrasing. I'd be inclined to say something like "field access expressions/method call syntax can perform autodereferencing". Thoughts?

Copy link
Contributor Author

@Kivooeo Kivooeo Apr 16, 2025

Choose a reason for hiding this comment

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

Oh, it's actually interesting because i fixed this typo in one of my squashed commit, seems it was lost somehow. But anyway. Do you prefer something like this?
.help = field access and method calls automatically dereference values (but raw pointers must be dereferenced manually)
Is that makes more sense?

Copy link
Contributor

@mejrs mejrs Apr 16, 2025

Choose a reason for hiding this comment

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

I've thought about it some more and I'm leaning towards:

the `.` operator will automatically dereference the operand, except if the operand is a raw pointer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this works too, but the only thing I’m not really sure about is the word operand. I feel like value is more commonly used, what do you think about it?

Copy link
Contributor

@mejrs mejrs Apr 16, 2025

Choose a reason for hiding this comment

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

The reference uses "operand" quite a lot, but I don't see it used often.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed, I'm going to stick with value variant since it sounds more natural

@rustbot

This comment has been minimized.

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2025
@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2025
@Kivooeo Kivooeo force-pushed the master branch 2 times, most recently from 13d0ac8 to 11a6b40 Compare April 16, 2025 22:02
@Kivooeo Kivooeo force-pushed the master branch 3 times, most recently from 340d7ee to 9ee67a5 Compare April 17, 2025 19:16
Comment on lines 42 to 47
= help: the `.` operator will dereference the value if needed
help: try using `.` instead
|
LL - attr::fn bar() -> String {
LL + attr::fn bar() . String {
|
Copy link
Member

Choose a reason for hiding this comment

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

I don't like the removal of these suggestions, this seems like a big step backwards.

I get the problem you are having with the diagnostics clashing, but I think we simply have to accept that. There isn't a good solution available at the moment. So you test will just have to be not-//@ run-rustfix. (the users can choose which suggestion to apply, so it's fine-ish to provide clashing suggestions)

The proper solution might look something like having a ast node<->diagnostics map, instead of emitting diagnostics in parser stash them there, then in the typechecker override the diagnostic if it was stashed. But we simply don't have the infrastructure to do this (and it'd be hard to add).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The suggestion in issue-118530-ice to replace -> with . feels off to me at first glance. Without this suggestions the error looks cleaner, but may be wrong.

I removed the rustfix in expr-rarrow-call.rs for two reasons:

  1. There was a conflict between replacing -> with . and -> with (*var)., which caused the tests to fail.
  2. Since the HIR provides more context than the parser, I opted to handle (*var). replacements there and removed it from the parser, keeping only a detailed error message with no suggestions in parser.

I considered creating separate errors for expr-call-rarrow and expr-call-rarrow-raw, but ran into issues:

  • Why not handle both in HIR? The parser replaces -> with ., so HIR can't tell if it was originally an arrow. This forces HIR to emit an error for a non-existent field.
  • Why not handle both in the parser? The parser lacks type information, making it impossible to distinguish between raw pointers and references.

Copy link
Member

Choose a reason for hiding this comment

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

There is no conflict in expr-rarrow-call.rs, I only see the parser diagnostic triggering there.

Since the HIR provides more context than the parser, I opted to handle (*var). replacements there and removed it from the parser, keeping only a detailed error message with no suggestions in parser.

As I already said, I don't agree with this decision and am asking you to revert this. The typecheck diagnostic is only triggered when the -> to . parser recovery triggers a type errors (like in the case of lhs being a pointer). So in most cases parser suggestion is valuable.

The conflict between diagnostics is annoying, but it is unavoidable with the current infra.

@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 Apr 20, 2025
@WaffleLapkin
Copy link
Member

@Kivooeo as errs said, a few days of inactivity is very common, reviewing PRs takes time and energy and people have lifes besides rustc :)

The sponsor page talks more about being on review rotation, doing PR review as a big part of the work. I still occasionally review PRs if I feel like it. I wouldn't assign myself to the PR if I wouldn't want to review it.

@rustbot

This comment has been minimized.

@rustbot rustbot added the has-merge-commits PR has merge commits, merge with caution. label Apr 20, 2025
@Kivooeo
Copy link
Contributor Author

Kivooeo commented Apr 20, 2025

@WaffleLapkin check this changes, tldr I reverted sugesstion attribute for Rarrow span in parser, removed rustfix in my testfile, updated error messages. I actually little bit ruined commits, starting this in master was awful idea, I will try to fix it tomorrow if could, if no I will close this and open new PR in separate branch
upd: fixed branch

@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 21, 2025
Copy link
Member

@WaffleLapkin WaffleLapkin left a comment

Choose a reason for hiding this comment

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

Looks good to me, modulo 1 nit

@@ -1,4 +1,3 @@
//@ run-rustfix
Copy link
Member

Choose a reason for hiding this comment

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

This can return to being run-rustfix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true, fixed

@Kivooeo Kivooeo force-pushed the master branch 2 times, most recently from acab75e to d9d8a9c Compare April 21, 2025 17:47
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@WaffleLapkin WaffleLapkin left a comment

Choose a reason for hiding this comment

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

Thanks!

@WaffleLapkin
Copy link
Member

bors r plus

@bors
Copy link
Collaborator

bors commented Apr 22, 2025

📌 Commit b5e8f1f has been approved by WaffleLapkin

It is now in the queue for this repository.

@bors bors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Apr 22, 2025
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 22, 2025
…enton

Rollup of 8 pull requests

Successful merges:

 - rust-lang#139617 (Use posix_spawn on cygwin)
 - rust-lang#139921 (improve diagnostic for raw pointer field access with ->)
 - rust-lang#140031 (compiletest: Fix deadline bugs in new executor)
 - rust-lang#140072 (handle function alignment in miri)
 - rust-lang#140104 (Fix auto diff failing on inherent impl blocks)
 - rust-lang#140124 (Update books)
 - rust-lang#140144 (Handle another negated literal in `eat_token_lit`.)
 - rust-lang#140149 (test_nan: ensure the NAN contant is quiet)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 22, 2025
…enton

Rollup of 8 pull requests

Successful merges:

 - rust-lang#139617 (Use posix_spawn on cygwin)
 - rust-lang#139921 (improve diagnostic for raw pointer field access with ->)
 - rust-lang#140031 (compiletest: Fix deadline bugs in new executor)
 - rust-lang#140072 (handle function alignment in miri)
 - rust-lang#140104 (Fix auto diff failing on inherent impl blocks)
 - rust-lang#140124 (Update books)
 - rust-lang#140144 (Handle another negated literal in `eat_token_lit`.)
 - rust-lang#140149 (test_nan: ensure the NAN contant is quiet)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 8089e31 into rust-lang:master Apr 23, 2025
6 checks passed
@rustbot rustbot added this to the 1.88.0 milestone Apr 23, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 23, 2025
Rollup merge of rust-lang#139921 - Kivooeo:master, r=WaffleLapkin

improve diagnostic for raw pointer field access with ->

This PR enhances the error messages emitted by the Rust compiler when users attempt to use the `->` operator for field access on raw pointers or when dereferencing is needed. The changes aim to provide clearer guidance, by suggesting the correct use of the `.` operator and explicit dereferencing.

**Before:**
```
help: `xs` is a raw pointer; try dereferencing it
   |
LL |         (*xs)->count += 1;
   |         ++  +
```

**Now:**
```
help: use `.` on a dereferenced raw pointer instead
   |
LL -         xs->count += 1;
LL +         (*xs).count += 1;
   |
```

I added extra clarification in the message. Since this error occurs in the parser, we can't be certain that the type is a raw pointer. That's why the message includes only a small note in brackets. (In contrast, the message above is emitted in HIR, where we *can* check whether it's a raw pointer.)

**Before:**
```
  --> main.rs:11:11
   |
11 |         xs->count += 1;
   |           ^^
   |
   = help: the . operator will dereference the value if needed
```
**After:**
```
--> main.rs:11:11
   |
11 |         xs->count += 1;
   |           ^^
   |
   = help: the `.` operator will automatically dereference the value, except if the value is a raw pointer
```
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.

None yet

9 participants