# Idea: puns in simple patterns

**URL:** <https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533>\
**Category:** language design\
**Created:** [July 8, 2019, 10:32pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533 "2019-07-08T22:32:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 8, 2019, 10:32pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/1 "2019-07-08T22:32:10Z")

</div>

I find myself doing the following _a lot_ for constructing and pattern matching structs:

```rust
let Foo {
  bar: &bar,
  baz: &mut baz,
} = foo;

```

It would be nice if one could just do this:

```rust
let Foo {
  &bar,
  &mut baz,
} = foo;

```

EDIT: and likewise for struct literals:

```rust
let foo = Foo { &mut baz, &bar };

```

Is there any ambiguity with doing that?

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [July 8, 2019, 11:06pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/2 "2019-07-08T23:06:17Z")

</div>

Yes, please, and in expressions too, especially `&field` and `*field`.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [July 8, 2019, 11:11pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/3 "2019-07-08T23:11:29Z")

</div>

We can potentially go as far as accepting an arbitrary pattern or expression in this position (except for type ascription) and report an ambiguity error only if the expression has more than one identifier.

```rust
FIELD_PAT = IDENT: PAT | PAT
FIELD_EXPR = IDENT: EXPR | EXPR

```

e.g.

```rust
let field = ...;
let s = Struct { *&(-(field))? }; // OK, equivalent to `Struct { field: *&(-(field))? }`
let z = Struct { field + other_field }; // ERROR, not clear which one is the field

```

There’s a natural limit on complexity since it’s hard to come up with anything complex having only one identifier, so it should be ok from readability point of view in practice.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [July 8, 2019, 11:34pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/4 "2019-07-08T23:34:07Z")

</div>

With type ascruption (always type ascription…) `K { field: T }` is ambiguous in expression position, so I suppose that’s a thing to ban. What about `K { self.foo }`? Should that be `K { foo: self.foo }`? (`self` is a keyword I guess?) If method calls are ok (`K { foo.bar() }` -\> `K { foo: foo.bar() }`) I think you’ll wind up with a lot of potentially wild combinations, possibly with some `.await` and `?` too.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [July 9, 2019, 4:03am UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/5 "2019-07-09T04:03:11Z")

</div>

> [@mcy](#):
>
> What about `K { self.foo }` ? Should that be `K { foo: self.foo }` ?

For prior art, that's what C# does in anonymous types: `new { foo.bar.baz }` is `new { baz = foo.bar.baz }`.

---

<div class="post-metadata">

**Author:** ![Dushistov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dushistov/32/4046_2.png) [@Dushistov](https://internals.rust-lang.org/u/Dushistov)\
**Post date:** [July 9, 2019, 12:39pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/6 "2019-07-09T12:39:18Z")

</div>

> [@mark-i-m](#):
>
> It would be nice if one could just do this:
> 
> ```rust
> let Foo {
> &bar,
> &mut baz,
> } = foo;
> 
> ```
> 
> Is there any ambiguity with doing that?

But you can do:

```rust
    let Foo {
        ref bar,
        ref mut baz
    } = foo;
    println!("bar {}", bar);
    *baz = 15;
    println!("bar {}", baz);

```

why introduce new syntax?

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 9, 2019, 1:48pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/7 "2019-07-09T13:48:14Z")

</div>

True, but it would be nice if you could also do it for struct construction:

```rust
let foo = Foo { *bar, &baz };

```

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 9, 2019, 1:52pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/8 "2019-07-09T13:52:40Z")

</div>

In my head this is what I imagined.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 9, 2019, 5:57pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/9 "2019-07-09T17:57:18Z")

</div>

Can you elaborate on what this would mean, precisely?

Field punning with `&` seems ambiguous to read in a way that punning without `&` doesn’t. For example, when you write `&baz` in a struct literal, that feels like it could mean “let the field baz be a reference to the local baz” (`baz: &baz`), or it could mean “let &baz be the local baz” (`baz: *baz`)? Generally only one of those will typecheck, but this still feels ambiguous to _read_ to me.

For pattern matching, I prefer `ref`. And for literals, I find the ambiguity confusing to read.

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 9, 2019, 6:36pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/10 "2019-07-09T18:36:38Z")

</div>

```rust
let foo = Foo { *bar, &baz };

```

in my mind this is equivalent to

```rust
let foo = Foo { bar: *bar, baz: &baz };

```

Maybe it’s just me, but I tend to think of pattern matching as the inverse of construction, so that the following works:

```rust
let Foo { *bar, &baz } = Foo { *bar, &baz };

```

In this example, `bar` is a reference in both the LHS and RHS, and `baz` is a non-reference binding in both the LHS and RHS.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 9, 2019, 6:49pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/11 "2019-07-09T18:49:12Z")

</div>

I understand that, but it’s not hard to read it as `Foo { *bar: bar, &baz: baz }` instead, because both field and value have the same name. I understand that’s not the intended reading, but that ambiguity makes it easy to stumble when reading.

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [July 9, 2019, 11:57pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/12 "2019-07-09T23:57:47Z")

</div>

In struct literals this doesn’t seem ambiguous to me at all, in light of what C# does (as @scottmcm mentioned, `new Foo { foo.bar.baz }` is `new Foo { baz = foo.bar.baz }`). It’s the “innermost” thing that needs to match, and the whole expression is the thing that gets evaluated and stored. This behaves exactly the same as any other expression, while your alternative interpretation feels more like something you would expect from a pattern.

It’s the use in patterns that feels weird to me. I might get used to `let Foo { &baz } = ...` because it simply transplants existing pattern syntax into field position, preserving a useful property of patterns: it matches actual concrete structure in the object (a pointer). But `let Foo { *bar } = ...` is problematic because `*bar` is not a pattern: there is no “anti-pointer” in the object’s structure to match, and `*bar` can never be a full pattern anyway (that’s why it’s a binding mode spelled `ref bar` instead).

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 10, 2019, 2:05am UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/13 "2019-07-10T02:05:25Z")

</div>

Hmm… yeah, I do see your point. For me, the bigger improvement in ergonomics would come from doing this for struct literals, rather than pattern matching.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [July 10, 2019, 7:36am UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/14 "2019-07-10T07:36:24Z")

</div>

An alternative for struct literals would be an auto ref/deref, such that you still write `Foo { bar }`, which is expanded to `Foo { bar: &bar }` or `Foo { bar: *bar }` if necessary

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 10, 2019, 1:04pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/15 "2019-07-10T13:04:05Z")

</div>

I’m personally not in favor of autoref/deref. I have found things like default-match bindings make my life much harder because what you write has all sorts of weird semantics behind it. I would rather have to go through an extra compiler error but know what the type of the binding is.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 10, 2019, 5:23pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/16 "2019-07-10T17:23:13Z")

</div>

Completely agreed.

---

<div class="post-metadata">

**Author:** ![repax](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/repax/32/1342_2.png) [@repax](https://internals.rust-lang.org/u/repax)\
**Post date:** [July 10, 2019, 8:20pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/17 "2019-07-10T20:20:04Z")

</div>

> [@mark-i-m](#):
>
> I’m personally not in favor of autoref/deref.

I suppose an opt-in compiler flag could be added for extra strictness.

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [July 10, 2019, 8:33pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/18 "2019-07-10T20:33:02Z")

</div>

I’m not too favorable of this approach either… in Fortran, C, and C++, the proliferation of flags and optional features means that it can be a pain to get anything to compile and run reproducibly because you have to find the right incantation.

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/chriskrycho/32/12576_2.png) [@chriskrycho](https://internals.rust-lang.org/u/chriskrycho)\
**Post date:** [July 10, 2019, 9:48pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/19 "2019-07-10T21:48:09Z")

</div>

Strongly agreed. One of the best things about Rust from a developer experience point of view—and very much _by contrast_ with the aforementioned languages—is that by and large you just run `cargo build`, and there’s not much notion of different strictness/warning levels/etc. (Modulo Clippy and a few other lints, perhaps, but that’s a rather different story.) Also, my experience with TypeScript in the last few years has me _very_ sad about configurations that change the strictness of a compiler—and it has more than once ended up with some very surprising intersections of (un)strictness along the way.

---

<div class="post-metadata">

**Author:** ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)\
**Post date:** [July 11, 2019, 8:08pm UTC](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533/20 "2019-07-11T20:08:46Z")

</div>

6 posts were split to a new topic: [A clippy lint to warn on default match binding modes](https://internals.rust-lang.org/t/a-clippy-lint-to-warn-on-default-match-binding-modes/10551)

[Next page](https://internals.rust-lang.org/t/idea-puns-in-simple-patterns/10533.md?page=2)
