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

Missing suggestion to dereference LHS of assignment when LHS is invalid #93980

Closed
compiler-errors opened this issue Feb 14, 2022 · 7 comments · Fixed by #94639
Closed

Missing suggestion to dereference LHS of assignment when LHS is invalid #93980

compiler-errors opened this issue Feb 14, 2022 · 7 comments · Fixed by #94639
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@compiler-errors
Copy link
Member

compiler-errors commented Feb 14, 2022

Given the following code:

fn main() {
    let mut x: Vec<()> = vec![()];
    x.last_mut().unwrap() = ();
}

The current output is:

error[E0070]: invalid left-hand side of assignment
 --> src/main.rs:3:27
  |
3 |     x.last_mut().unwrap() = ();
  |     --------------------- ^
  |     |
  |     cannot assign to this expression

For more information about this error, try `rustc --explain E0070`.

Ideally the output should look like:

error[E0070]: invalid left-hand side of assignment
 --> src/main.rs:3:27
  |
3 |     x.last_mut().unwrap() = ();
  |     --------------------- ^
  |     |
  |     cannot assign to this expression

Note: consider dereferencing the left-hand side
3 |     *x.last_mut().unwrap() = ();
        +

For more information about this error, try `rustc --explain E0070`.

The root cause seems to be the coersion error being suppressed, since there is already logic that suggest dereferencing the LHS of an assignment operator. In fact, this diagnostic code path is being hit, but somewhere along the way the diagnostic is being canceled (hence the fact that we only see this "invalid left-hand side of assignment" error being emitted and not an error about not being able to relate &mut () and ().)

@compiler-errors compiler-errors added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 14, 2022
@ChayimFriedman2
Copy link
Contributor

@rustbot claim

The culprit is here:

if !lhs.is_syntactic_place_expr() {
// We already emitted E0070 "invalid left-hand side of assignment", so we
// silence this.
err.delay_as_bug();
}

I'm not quite sure how to solve this. After all, the comment is correct. Do we want to show both errors? Or just attach the help to the "invalid left-hand side of assignment" error?

@compiler-errors
Copy link
Member Author

@ChayimFriedman2, amazing find!

If we remove that delay-as-bug, do we see a lot of unnecessary new errors being emitted in the ui tests?

On the other hand, it might be useful just to special case this logic and attach it to the "invalid left-hand side" error.

@ChayimFriedman2
Copy link
Contributor

Here's what the compiler emits if I comment the above code out:

error[E0070]: invalid left-hand side of assignment
 --> t.rs:3:27
  |
3 |     x.last_mut().unwrap() = ();
  |     --------------------- ^
  |     |
  |     cannot assign to this expression

error[E0308]: mismatched types
 --> t.rs:3:29
  |
3 |     x.last_mut().unwrap() = ();
  |     ---------------------   ^^ expected `&mut ()`, found `()`
  |     |
  |     expected due to the type of this binding
  |
help: consider dereferencing here to assign to the mutable borrowed piece of memory
  |
3 |     *x.last_mut().unwrap() = ();
  |     +

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0070, E0308.
For more information about an error, try `rustc --explain E0070`.

Not so bad, but maybe it can become more verbose in other cases and not emitting redundant errors is always better. I'll try to update the logic so it'll just append the help.

@estebank
Copy link
Contributor

In the surrounding code to

self.check_lhs_assignable(lhs, "E0070", *span);

you have access to the types and the expr, so you might be able to easily call the code that provides the suggestion in E0308 from there.

@ChayimFriedman2
Copy link
Contributor

@estebank The problem is that this code is not self-contained; it's inside check_ref() that performs a bunch of other suggestions. I'm working on extracting it and improving it BTW because it has some other reported bugs (#93983, #46276) and I have to refactor it anyway.

@ChayimFriedman2
Copy link
Contributor

@rustbot release-assignment

I don't have time for that now. If somebody wants to pick it and work on it, feel free.

@compiler-errors
Copy link
Member Author

@rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants