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

mut keyword alone unexpectedly dereferences value in pattern matching #105647

Open
yescallop opened this issue Dec 13, 2022 · 5 comments
Open

mut keyword alone unexpectedly dereferences value in pattern matching #105647

yescallop opened this issue Dec 13, 2022 · 5 comments
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@yescallop
Copy link
Contributor

yescallop commented Dec 13, 2022

I tried this code:

let [a] = &[()];
let [mut b] = &[()];
b = a;

I expected to see this happen: the mutable binding b has type &(), and thus the compilation succeeds without any error.

Instead, this happened: the mutable binding b has type (), and the compilation fails with error:

error[E0308]: mismatched types
  --> src\lib.rs:80:9
   |
79 |     let [mut b] = &[()];
   |          ----- expected due to the type of this binding
80 |     b = a;
   |         ^ expected `()`, found `&()`
   |
help: consider dereferencing the borrow
   |
80 |     b = *a;
   |         +

Meta

rustc --version --verbose:

rustc 1.68.0-nightly (37d7de337 2022-12-12)
binary: rustc
commit-hash: 37d7de337903a558dbeb1e82c844fe915ab8ff25
commit-date: 2022-12-12
host: x86_64-pc-windows-msvc
release: 1.68.0-nightly
LLVM version: 15.0.6
@yescallop yescallop added the C-bug Category: This is a bug. label Dec 13, 2022
@RedDocMD
Copy link
Contributor

I don't think this is a bug. a resolves to &() because of match ergonomics while b is matched to () because b is explicitly marked as mut and so match ergonomics don't apply.

@Antikyth
Copy link

I don't think this is a bug. a resolves to &() because of match ergonomics while b is matched to () because b is explicitly marked as mut and so match ergonomics don't apply.

Are the match ergonomic rules listed somewhere I can learn more about? When they do or don't apply, as you say, isn't very intuitive to me, if it's explained somewhere I would like to learn more about it :)

@RedDocMD
Copy link
Contributor

The Match Ergonomics RFC is a very good read on this. If you're in a hurry, you can start reading from here.

@yescallop
Copy link
Contributor Author

yescallop commented Dec 13, 2022

I also notice that this issue was last mentioned by @varkor at #64586 (comment).

If I understand the match ergonomics RFC correctly, the code above currently gets desugared to:

let &[ref a] = &[()];
let &[mut b] = &[()]; // The default binding mode `ref` gets overridden by `mut`.
b = a;

which is quite a bit unintuitive. The desugared code I'd expect should be like this:

let &[ref a] = &[()];
let mut b = match &[()] {
    &[ref b] => b,
};
b = a;

I believe that both this issue and #64586 can be and ought to be fixed by a future RFC, in which we should probably consider another approach other than the current one where the default binding mode can be unexpectedly overridden.

@estebank estebank added T-lang Relevant to the language team, which will review and decide on the PR/issue. A-patterns Relating to patterns and pattern matching labels Dec 13, 2022
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 18, 2024
Experiment: lint resetting `mut` bindings

We would like to fix rust-lang#105647 in rust 2024. To evaluate the breakage, I wrote a lint that detects the cases where there would be a difference between now and rust 2024.

I'd like to request a crater run with `dereferencing_mut_binding` set to `deny` to see how many crates would be affected.
@Nadrieril
Copy link
Member

Nadrieril commented Feb 11, 2024

Hi! I was hoping to get this fixed on the new edition. I initially had a complex proposal but turns out the issue is pretty straightforward:

  • it's easy to detect patterns that use mut in this surprising way (did it here for a crater run);
  • it's straightforward to change a pattern so it doesn't rely on that (simply desugar the match ergonomics, i.e. add & and ref as appropriate);
  • it's easy to make mut behave like it should in the new edition.

Moreover, the lang team has expressed general agreement to solve this for 2024 (contingent on details being ironed out). But, I'm finding no bandwidth to work on this. So, if anyone wants to take over this, please do. I'm happy to answer questions if you're not entirely clueless about what this would involve (mostly patience to go through the processes, which I don't have enough of).

And if not, well we can take our time and get it for 2027.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants