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), writingmut
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 aref mut
DBM treated as aref
one under Rule 5), set the DBM toref
whenever we would otherwise set it toref mut
. - Rule 4: If an
&
or&mut
pattern is being matched against a non-reference type and if the DBM isref
orref 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 aref mut
DBM under Rule 4), act as if the type were a shared reference instead (or that theref mut
DBM is aref
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 isref
orref 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 isref
orref 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