# Grammatical ambiguity around \`catch\` blocks

**URL:** <https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807>\
**Category:** language design\
**Created:** [February 17, 2017, 8:56pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807 "2017-02-17T20:56:51Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [February 17, 2017, 8:56pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/1 "2017-02-17T20:56:51Z")

</div>

So @cramertj has been working on implementing `catch` blocks, and they ran into an interesting issue with the grammar. I think we believed that `catch { <expr> }` would be legal to add without ambiguity because the only thing it could be was a struct initializer, and those have the form `Struct { (field: expr)* }`. But with the new field-init-shorthands, `catch { foo }` could be either a catch block or a struct initializer.

Thoughts on how we should handle this? I suspect that very little code actually uses `catch` as the name of a struct or enum variant, but of course it’s possible.

Note that local variables named `catch` should be ok, since the “keyword” would only take effect when followed by `{` (and, e.g., `while catch {..}` would therefore parse as `while (catch) { ..}`, given the restrictions on expressions that appear in a `while`).

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [February 17, 2017, 9:01pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/2 "2017-02-17T21:01:54Z")

</div>

Options I see:

- add some system to let us grow new keywords (that’s a bigger topic…)
- breaking change for structs named `catch` (we’d want to measure, do a warning period)
- resolve based on whether a struct named `catch` is in scope (much as we do for pattern bindings; not my preferred plan, but probably an option)
- use `do`, which is reserved 🙂

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [February 17, 2017, 9:08pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/3 "2017-02-17T21:08:52Z")

</div>

- Use `do` as a sort of keyword escape?
  - `do catch { <expr> } // if you don't mind`
  - (sort of joking, but maybe…)

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [February 17, 2017, 9:18pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/4 "2017-02-17T21:18:54Z")

</div>

@cramertj points out that my reasoning is false-ish, in that type ascription means that `catch { foo: bar }` is also ambiguous. But it doesn’t really change the fundamental options, though I guess it makes the idea of a “context-dependent parse” too complex to really imagine (not that I favored that anyhow).

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [February 17, 2017, 9:21pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/5 "2017-02-17T21:21:43Z")

</div>

Frankly, I’d be amazed if someone named any `struct` `catch`. We should probably try to do a search across all [crates.io](http://crates.io) and maybe github repos.

**EDIT** : e.g. [GitHub search for `"struct catch"` in `.rs` files](https://github.com/search?l=Rust&p=1&q=%22struct+catch%22&type=Code&utf8=%E2%9C%93). Oh and `enum Foo { catch {...} } use self::Foo::*;` is entirely valid too, but harder to find.

---

<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:** [February 17, 2017, 9:27pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/6 "2017-02-17T21:27:15Z")

</div>

Heh.

> I'm for the simplest solution - always treat `catch {` in expression positions as start of a catch block. Nobody calls their structures `catch` anyway.

[[link](https://github.com/rust-lang/rust/issues/31436#issuecomment-180719503)]

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [February 17, 2017, 9:57pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/7 "2017-02-17T21:57:49Z")

</div>

Heh, I wondered if this came up on the thread before, but I course I didn’t **actually search**. Should have known it’d be you who brought it up (since you seem to be quite adept at uncovering such problems).

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [February 17, 2017, 10:28pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/8 "2017-02-17T22:28:57Z")

</div>

> [@nikomatsakis](#):
>
> resolve based on whether a struct named catch is in scope (much as we do for pattern bindings; not my preferred plan, but probably an option)

A variant of this is to "refuse the temptation to guess" (in Python parlance) when there's a struct called `catch` in scope. That is, emit an error if we encounter a `catch { ... }` that could either refer to a struct called `catch` or be a catch expression. This is still a breaking change, but only for code using field init shorthand[\*], which has recently been stabilized but hasn't hit stable yet. So, all existing code using `catch { field: expr }` as struct initializer would continue to work, but any of the below would get an error:

- writing a now-newly-stable shorthand initializer like `catch { field }`, or
- writing a `catch` expression while a struct named `catch` is in scope, or
- having a `catch` expression somewhere and introducing a struct called `catch`

[\*] This doesn't address type ascription, though. (But I recall chatter doubting the use of type ascription, so maybe it may not come to fruition after all?)

---

<div class="post-metadata">

**Author:** ![naicode](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/naicode/32/2254_2.png) [@naicode](https://internals.rust-lang.org/u/naicode)\
**Post date:** [March 14, 2017, 9:38pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/9 "2017-03-14T21:38:13Z")

</div>

might be a horrible idea but what about `catch! { <expr> }` through that would collide with macros named catch, which might be even likelier then a struct named catch.

---

<div class="post-metadata">

**Author:** ![anon32976453](https://avatars.discourse-cdn.com/v4/letter/a/49beb7/32.png) [@anon32976453](https://internals.rust-lang.org/u/anon32976453)\
**Post date:** [March 15, 2017, 12:33am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/10 "2017-03-15T00:33:05Z")

</div>

> [@nikomatsakis](#):
>
> add some system to let us grow new keywords (that's a bigger topic...)

This should be done sooner rather than later, otherwise Rust will start to accumulate hacks and context keywords and will become difficult to parse. Let's not become another C++ 😉

My suggestion is to have a gradual process of keyword reservation:

1. first add a warning that an identifier will become reserved in the future and suggest renaming.
2. after a period of time (one release cycle?) make it a hard error.
3. after another period of time, reserve the keyword.

In addition, there should be tooling somewhere to apply auto rename for to-be-reserved identifiers in order to help automate the transition.

---

<div class="post-metadata">

**Author:** ![scott](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scott/32/1564_2.png) [@scott](https://internals.rust-lang.org/u/scott)\
**Post date:** [March 15, 2017, 12:56am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/11 "2017-03-15T00:56:32Z")

</div>

> [@anon32976453](#):
>
> My suggestion is to have a gradual process of keyword reservation:
> 
> 1. first add a warning that an identifier will become reserved in the future and suggest renaming.
> 2. after a period of time (one release cycle?) make it a hard error.
> 3. after another period of time, reserve the keyword.

There's a growing list of other syntax we would ultimately _like_ to repurpose in this way, but we generally avoid breaking the ability to run code that worked on 1.x on 1.y where y \> x except in cases where the code was exploiting a compiler bug or was just a terrifically rare construction. Our stability guarantees demand we wait until 2.0 for most of these.

I assume the system @nikomatsakis alludes to for introducing new keywords would involve some kind of opt-in to make it not a breaking change. (@nikomatsakis correct me if I'm wrong.)

---

<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:** [March 15, 2017, 8:38am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/12 "2017-03-15T08:38:59Z")

</div>

Maybe something involving `?`, since that’s sparsely used and related to what this does anyway? For example: `catch? { foo()?.bar()?.baz()? }`

Alternatively, whole-function-in-a-catch-block would help the `Ok(())` issue, so it would be cool if the catch syntax could be something that would work at the block-for-the-function level. Non-serious proposal for illustrative purposes: `fn four<E>() -> Result<i32, E> ¿{ 4 }`, or the above would be `¿{ foo()?.bar()?.baz()? }`

Also, is there a way that `throw` can be reserved inside a `catch` block, so that an attempt to add that sugar later won’t hit similar grammar problems?

---

<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:** [March 15, 2017, 1:06pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/13 "2017-03-15T13:06:47Z")

</div>

Perhaps we should reconsider some of the keywords that are not ambiguous, e.g.:

```rust
do {
    foo()?.bar()
}

```

---

<div class="post-metadata">

**Author:** ![vadimcn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vadimcn/32/2789_2.png) [@vadimcn](https://internals.rust-lang.org/u/vadimcn)\
**Post date:** [March 15, 2017, 5:42pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/14 "2017-03-15T17:42:27Z")

</div>

So what does the Language Team think about having crates declare language version they are targeting?

---

<div class="post-metadata">

**Author:** ![naicode](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/naicode/32/2254_2.png) [@naicode](https://internals.rust-lang.org/u/naicode)\
**Post date:** [April 3, 2017, 9:51pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/15 "2017-04-03T21:51:01Z")

</div>

> [@vadimcn](#):
>
> about having crates declare language version they are targeting?

If a language version (target) is introduced I believe it should be crate specific, aka mixing crates using different language versions should be fine. I would even consider making it module! specific (or having some major.minor scheme where all modules in the same crate have to have the same major lang version, but possible different minor lang versions)

I think such a language version should be for some new features which introduce some **syntactical only** breaking changes . Also this could be extended in "some" degree to API changes, **as long as this won't lead to incompatibilities with existing libraries using a older language version**. Note that I mainly mean incomparability of using older libraries in libs/progs using a newer language version. I think the other way around it is fine as long as the library still can be used, through maybe not some of it's part's (e.g. parametrized modules or some other strange, but probably use full, thinks).

This can be used to introduce keywords which change crate/module/function internal aspects only, like `catch`. This could also be used to "phase out" some other part's, which else wise would, at most, generate warning, e.g. maybe the (in the future) old macro system (\<- not completely sure about this myself).

Through I think it should **not be called language version** we already have a language version i.e. the rust(c) version. Maybe some think like _syntax version_ might be a better name (but then if might actually be a bit more then syntax...).

Oh and add `syntax_version = <newest>` to new crates and additionally make sure "nice" error messages are produced when accidentally colliding with "old" syntax versions.

Alternative a `#[syntax_features=...]` crate/module(/function?) level annotation can work too (including stable).

Lastly `do catch { ... }` is not "that" bad 🙂

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [April 3, 2017, 10:22pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/16 "2017-04-03T22:22:26Z")

</div>

Probably worth linking to [[pre-rfc] Stable features for breaking changes](https://internals.rust-lang.org/t/pre-rfc-stable-features-for-breaking-changes/5002) at this point since a good chunk of that thread has been discussing the idea of “epochs” as a way of introducing minor breaking changes such as making catch a keyword, and the details of that idea seem to fit the spirit of your post.

---

<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:** [April 3, 2017, 10:23pm UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/17 "2017-04-03T22:23:33Z")

</div>

Was a decision ever made on `catch` syntax? Did it just land as `do catch` for now?

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [April 4, 2017, 10:34am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/18 "2017-04-04T10:34:21Z")

</div>

> [@scottmcm](#):
>
> Did it just land as do catch for now?

For now. This is not meant to be a permanent solution.

---

<div class="post-metadata">

**Author:** ![bestouff](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bestouff/32/2595_2.png) [@bestouff](https://internals.rust-lang.org/u/bestouff)\
**Post date:** [April 16, 2017, 9:43am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/19 "2017-04-16T09:43:19Z")

</div>

How about reserving a big bunch of keywords, once and for all (i.e. `catch`, `await`, `class`, etc.). Ah, I see that you already had the idea: [https://github.com/rust-lang/rust/issues/10293](https://github.com/rust-lang/rust/issues/10293) - well, how about reopening that ?

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [April 17, 2017, 10:05am UTC](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807/20 "2017-04-17T10:05:24Z")

</div>

Well, it’s a bit late now. =) I’d prefer to solve this permanently with [the concept of epochs](https://internals.rust-lang.org/t/pre-rfc-stable-features-for-breaking-changes/5002/9?u=nikomatsakis), which is exactly the sort of thing we were anticipating when we closed #10293. I think the reason I am not keen on reserving “a bunch of keywords” is that then we wind up picking keywords not based on whether they are the Right Keyword, but based on whether we happen to have reserved it. OTOH, the whole Epoch discussion hasn’t really reached consensus yet, and in particular it’s not clear how often we might want to declare a fresh epoch – if the idea is to do this very rarely, then perhaps it makes sense that, in the next epoch, we reverse course on #10293 and do indeed reserve a bunch of common keywords.

[Next page](https://internals.rust-lang.org/t/grammatical-ambiguity-around-catch-blocks/4807.md?page=2)
