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

Mutable let-else binding produces dereferenced type when deconstructing references #112545

Closed
udoprog opened this issue Jun 12, 2023 · 5 comments
Closed
Labels
C-bug Category: This is a bug.

Comments

@udoprog
Copy link
Contributor

udoprog commented Jun 12, 2023

I tried this code:

pub fn main() {
    let value: Option<u64> = Some(10);
    let other: u64 = 20;

    let Some(mut value) = &value else {
        panic!();
    };

    value = &other;
}
error[[E0308]](https://doc.rust-lang.org/stable/error_codes/E0308.html): mismatched types
 --> src/main.rs:9:13
  |
5 |     let Some(mut value) = &value else {
  |              --------- expected due to the type of this binding
...
9 |     value = &other;
  |             ^^^^^^ expected `u64`, found `&u64`

Note a non-mutable binding works as expected:

let Some(value) = &value else {
  panic!();
};

In my mind, value should be a mutable binding to &u64, but the desugaring performed seems to cause the mutable binding in particular to result in attempting to move the de-referenced value.

This is apparent when dealing with non-copy types:

pub fn main() {
    let value: Option<String> = Some(String::from("Hello"));
    let other: String = String::from("World");

    let Some(mut value) = &value else {
        panic!();
    };

    value = other;
}
error[[E0507]](https://doc.rust-lang.org/stable/error_codes/E0507.html): cannot move out of a shared reference
 --> src/main.rs:5:27
  |
5 |     let Some(mut value) = &value else {
  |              ---------    ^^^^^^
  |              |
  |              data moved here
  |              move occurs because `value` has type `String`, which does not implement the `Copy` trait

Meta

rustc --version --verbose:

rustc 1.70.0 (90c541806 2023-05-31)
@udoprog udoprog added the C-bug Category: This is a bug. label Jun 12, 2023
@udoprog udoprog changed the title Mutable let-else binding produces owned type when deconstructing references Mutable let-else binding produces dereferenced type when deconstructing references Jun 12, 2023
@est31
Copy link
Member

est31 commented Jun 12, 2023

Your first snippet fails for me with a type mismatch, and if I change the last line to read value = other; as suggested by the error, it works.

As for the second snippet, it causes the same error with an if let:

pub fn main() {
    let value: Option<String> = Some(String::from("Hello"));
    let other: String = String::from("World");

    /*let Some(mut value) = &value else {
        panic!();
    };

    value = other;*/
    if let Some(mut value) = &value {
        value = other;
    } else {
        panic!();
    }
}
error[[E0507]](https://doc.rust-lang.org/nightly/error_codes/E0507.html): cannot move out of a shared reference
  --> src/main.rs:10:30
   |
10 |     if let Some(mut value) = &value {
   |                 ---------    ^^^^^^
   |                 |
   |                 data moved here
   |                 move occurs because `value` has type `String`, which does not implement the `Copy` trait
   |
help: consider borrowing the pattern binding
   |
10 |     if let Some(ref mut value) = &value {
   |                 +++

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

@CryZe
Copy link
Contributor

CryZe commented Jun 12, 2023

This is a known bug with match ergonomics. I was pushing for it to get fixed for Rust 2021, but unfortunately it never got fixed.

@udoprog
Copy link
Contributor Author

udoprog commented Jun 12, 2023

This is a known bug with match ergonomics

I was looking for something related to match ergonomics (didn't remember the name), but struggled to find it. Do you have a tracking issue for this bug?

@CryZe
Copy link
Contributor

CryZe commented Jun 12, 2023

It's been discussed here: #64586 (comment)

Also this RFC intends to somewhat address it too by making it more explicit: rust-lang/rfcs#3410 (comment)

@ChrisDenton ChrisDenton added the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jul 16, 2023
@Nadrieril
Copy link
Member

This comes up regularly. The lang team will discuss fixing this in the 2024 edition! In the meantime, I'm closing this as a duplicate of #105647

@Nadrieril Nadrieril closed this as not planned Won't fix, can't repro, duplicate, stale Dec 1, 2023
@fmease fmease removed the needs-triage-legacy Old issue that were never triaged. Remove this label once the issue has been sufficiently triaged. label Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

6 participants