Idea: puns in simple patterns

But auto ref/deref may work for Foo { bar } but it does not work for Foo { mut bar }.

It would be cool to see Foo { &bar, &mut baz } but I wonder what would happened to Foo { bar? } or Foo { baz.await } or Foo { bar.field }?

That’s why I like @petrochenkov’s proposal from above, namely that we do a transformation like this:

Given a struct Foo defined like this:

Foo {
  field0: T0,
  field1: T1,
  fieldN: TN,

and the following struct literal:

Foo { expr0, expr1, ..., exprN }

where the only identifier in expr0 is field0, in expr1 is field1, …, in exprN is fieldN, then we desugar to the following struct literal:

Foo {
  field0: expr0,
  field1: expr1,
  fieldN: exprN,

I can very easily see that leading to errors. Consider math on a vector or matrix that wants to intentionally shuffle around components, for instance.

Also, just to confirm, would “one identifier” rule out dotted expressions like this?

struct V3 { x: f64, y: f64, z: f64 }
fn shuffle(v: V3) -> V3 {
    V3 { v.y, v.z, v.x }

I can easily see a C programmer writing that, because C allows initializing structs positionally.This needs to continue producing an error, rather than incorrectly producing an identity function.

I can easily imagine the same kind of error with expressions that have only one identifier.

(Even for the existing field punning, I can imagine code that will erroneously compile; I’d favor having, for instance, a lint for cases that involve structs containing entirely fields of the same type and same-length short names where the field puns appear out of order.)


I actually made this error with the existing shortcut once.

I needed to swap two fields and wrote something like this:

let s = if lo <= hi {
    S { lo, hi }
} else {
    S { hi, lo }

I can see at least two ways we could catch that with a lint.

The least likely to cause false positives: if you write two struct initializers with field puns in the same function with fields in different orders, lint.

Also, the one I mentioned in the previous post involving an out-of-order struct initializer with field puns that consist entirely of fields with the same name-length and same type. That could lead to false positives, but you can trivially fix those by reordering the fields or by labeling the fields.


It’s apparent that this can cause bugs regardless of what is proposed here, so it’s perhaps not very relevant to this discussion. At least, I don’t see how this proposal makes that situation any worse.

It seems to me that allowing arbitrary expressions (with only the “one identifier” limit) makes bugs more likely.

1 Like

My thinking is to disallow the use of dot expressions or keywords. We could also disallow non-unary operators. I think with all of these restrictions we can still improve ergonomics for the most common cases.

I do like the idea of a lint, though.

While I don’t personally have a use for it, I don’t have any strong objection to allowing this for most unary operators, if that would help.

I would find it quite confusing to permit &, though, precisely because of potential confusion with what ref means.

It seems like it would be a bit bizzare to disallow only &, wouldn’t it? Also, I expect & and * to be the most common use cases for this…

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.