Match ergonomics 2024 poll

I'm working on changes to match ergonomics for the 2024 edition. As part of that, I would like people's opinion on a design question. Consider the pattern below, which does not use match ergonomics:

let &[&mut ref x] = &[&mut 42];

What should the match-ergonomics version of the above pattern look like?

  • let [&mut x] = &[&mut 42];
  • let [&x] = &[&mut 42]; or let &[x] = &[&mut 42];
  • Both of the above should work
  • Neither should work
0 voters

If you chose one of the first 2 options: if you had to choose between both or neither, which would you prefer?

  • Both
  • Neither
0 voters

In let [&x] = &[&mut 42]; or let &[x] = &[&mut 42];, how can you possibly match &mut 42 with &x? Does this means that x would have type &42 here, and with this, would be read only?

Correct.

This is the only thing in the OP that kind of makes sense to me. If you had asked whether the initial non-'ergonomic' example even compiles, I would probably have said no, but with very little confidence.

8 Likes

You presented three scenarios but only two options.

I don't think 2 or of the 3 scenarios should work and there's no poll option corresponding to that. If both scenarios "must" work for the second option, I'd vote for none working.

1 Like

That's what I was going for yes. However, I'd be curious to hear which single scenario of the latter two you think should be supported, and why.

My thinking is that getting &mut out of it is not possible, so & &mut could be simplified to & &. So then to get a reference to x:

let [x] = 

or

 let &[x] =

And anything with &x or &mut x should give a dereferenced value.


The original &mut ref syntax is explicitly performing the only sensible conversion there can be to get a reference, so it's a needless detail that can be omitted entirely.

1 Like

My comment was prompted more by a negative reaction to one of the two scenarios. I think this scenario:

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

should not be supported, because "unwrapping" a &mut with a & should be an error. Moreover, knowing what let [&x] = &[&i] does, I'd expect it to copy (or attempt to move) i, if anything.


I'm not sure I'd really want let &[x] to work either. But if changing the meaning of [let &mut x][1] is on the table, I'd probably have to read up on the entire gamut of changes to form a solid opinion. Consistency across the whole system is important.


  1. which compiles today ↩︎

3 Likes

In the current draft design, if this example were to be supported, then the & in the pattern would unwrap the outer & from the scrutinee, not the inner &mut. (The design does allow & patterns to "unwrap" &mut, but that's not what going on here.)

(Assuming you mean let [&mut x] ) The plan is to change the meaning, yes. You can find the draft RFC here. (Please use this topic to discuss only the options in the poll; other comments about the RFC draft should go to this Zulip thread.)

1 Like

The combination of "& can match &mut" and "an inner & can match an outer &" seems error-prone, particularly if someone isn't completely sure what the type of the scrutinee is. For instance, suppose that you don't realize the thing you're matching has a reference on the outside of the type (e.g. &[&mut T]), and then you write [&x] expecting the x to match the type T. This would then end up producing a type other than the one you expected, because your &, rather than being an error, matches the outer &.

2 Likes

I don't see how & matching against &mut makes a difference here? You'd have the result matching an [&x] pattern against a &[&T] scrutinee.

I've added a followup question to the poll, for those who chose one of the first 2 options.

I voted for &[x] / [&x] working to bind x: &i32, but with a small caveat — if/when patterns see through "DerefPure" containers, the same adjustment from binding P<T> to binding &T should apply to them, and to do so for let &x = &&mut 42 as well.

I also voted for neither being preferable to both. I can see [&mut x] potentially binding mut x: &i32, x: i32, or x: &i32 depending on specifics. Looking at it more makes me more understanding of how the third option gets accepted, but the ambiguity between &«mut x» and «&mut» x doesn't sit well with me.

This exploration has made me more appreciative of the current state. Although for the most case, default binding modes prefers you using a [x] pattern, getting x: &&mut i32, and utilizing deref coercion, anyway. I'm almost down to just entirely deprecate & patterns in non-default binding modes, honestly.

(That could be more interesting than it first seems, even — co-opt & patterns to shift from a ref binding mode back to by-move, but not for destructuring references anymore, instead using the general deref pattern for explicit destructure.)

1 Like

My main gripe about how default binding modes work today is that (at least it feels like) you have to explain/understand all of binding modes in order to explain/understand what gets bound in a pattern that utilizes mut or & in a position with a non-default default binding mode. I have no idea how to address this (feeling).

Default binding modes do generally feel good when no explicit manipulation of the binding mode is done. It's the complexity cliff this results in when you want something other than that convenient default that things get awkward.

The aim of the edition changes is to simplify these things:

  • mut will no longer have any effect on whether the binding is by-reference or by-value
  • & and &mut will ~always strip off a single reference

If it helps, after reading the thread, I feel like I failed a college entrance exam! :sweat_smile:

"Neither" seems safer now.

9 Likes

I'm not voting, because to be honest I don't even know what this should do currently. My reaction was "Is that valid? What does it even mean?".

4 Likes

RFC is posted: Match ergonomics 2024 by Jules-Bertholet · Pull Request #3627 · rust-lang/rfcs · GitHub

It specifies that none of the examples from the poll should work.

The question is unclear to me – I think the poll sorts answers by popularity, so "first two" is ambiguous.

Also one of the answers included "or" with two examples, do you mean that answer? And btw the option with "or" includes one half that I agree with and other that I disagree with, so I didn't want to vote for such mixed option.