rust-lang / rust-lang/rust

Fix discrepancy between match ergonomics Rule 4 and implementation

Open
#127,559 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-discussion T-lang
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

In our 2024-06-26 design meeting on match ergonomics (part 3):

...we decided on a slate on rules:

  • Rule 1: When the DBM (default binding mode) is not move (whether or not behind a reference), writing mut on a binding is an error.
  • Rule 2: When a reference pattern matches against a reference, do not update the DBM.
  • Rule 3: If we've previously matched against a shared reference in the scrutinee (or against a ref DBM under Rule 4, or against a mutable reference treated as a shared one or a ref mut DBM treated as a ref one under Rule 5), set the DBM to ref whenever we would otherwise set it to ref mut.
  • Rule 4: If an & or &mut pattern is being matched against a non-reference type and if the DBM is ref or ref mut, match the pattern against the DBM as though it were a type.
  • Rule 5: If an & pattern is being matched against a mutable reference type (or against a ref mut DBM under Rule 4), act as if the type were a shared reference instead (or that the ref mut DBM is a ref DBM instead).

We then, in:

...amended Rule 4 to read as follows:

  • Rule 4: If an & pattern is being matched against a non-reference type or an &mut pattern is being matched against a shared reference type or a non-reference type, and if the DBM is ref or ref mut, match the pattern against the DBM as though it were a type.

(Emphasis highlights the diff.)

We did that so that it would accept cases like this:

let [&mut x] = &mut [&T]; //~ x: &T

It had been proposed the amended Rule 4 was equivalent to an earlier proposal to accept the union of the code accepted under either the original Rule 4 (the "structural" variant) or under Rule 4 (early) (the "early" variant). (Rule 4 (early) breaks the primacy of structural matching by matching first against the DBM.)

However, in discussion, @WaffleLapkin found a case that shows that the amended Rule 4 isn't equivalent to accepting the union:

let [&&mut x] = &[&mut T];

This case is accepted by the early variant but not by the amended Rule 4.

However, this is accepted by the implementation by @Jules-Bertholet, as merged in:

We could adjust the implementation to match the accepted RFC.

Or, conceivably, we could amend the statement of Rule 4 to align with the implementation. If we did that, the re-revised statement of Rule 4 then would be:

  • Rule 4 (extended 2): If an & pattern is being matched against a mutable reference type or a non-reference type, or if an &mut pattern is being matched against a shared reference type or a non-reference type, and if the DBM is ref or ref mut, match the pattern against the DBM as though it were a type.

(Emphasis highlights the diff.)

Note that this would have the effect of taking precedence over Rule 5.

However, this too doesn't accept strictly more code. Because under the originally-amended Rule 4, we accept this:

let [&x] = &[&mut T]; //~ x: &T

...but under the extended 2 rule, that would be rejected:

let [&x] = &[&mut T]; //~ x: &mut T
//~^ ERROR cannot move out of non-copy array

We'll analyze this further, then nominate if we decide that the rule should be changed rather than the implementation. We're not really worried about it; we see a number of acceptable options here (including implementing the Rule 4 as written).

(If it were to come to it, we don't need to stabilize Rule 4 immediately. We only need to stabilize Rule 1 and Rule 2 in Rust 2024.)

Tracking:

@rustbot labels +T-lang

cc @Jules-Bertholet @Nadrieril

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the match ergonomics discussion in issues #127559, #127257, and the tracked issue #123076, then compare the amended Rule 4 with the implementation merged in pull request #127369. Use the provided pattern examples to identify where the implementation and accepted rule differ. Done requires a resolved language-rule decision and corresponding implementation alignment; no source file or test is named.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.