# Bikeshed: Rename \`catch\` blocks to \`fallible\` blocks

**URL:** https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121
**Category:** language design
**Created:** [March 23, 2018, 6:09am UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121 "2018-03-23T06:09:25Z")
**Posts on this page:** 20
**Page:** 1

<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 23, 2018, 6:09am UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/1 "2018-03-23T06:09:25Z")

</div>

I was contemplating `catch` blocks again, and musing on the feedback that we shouldn’t use exception terminology since we don’t have exceptions, and the fact that catch blocks in [RFC #243](https://github.com/rust-lang/rfcs/pull/243) don’t really work like catch blocks in languages like Java anyway (nor like `handle` in SML).

What if we renamed them `fallible` blocks? F[o](https://play.rust-lang.org/?gist=1965eeb037b62c06c13609f77ece8fd1&version=nightly)r example:

```nohighlight
type SizeHint = (usize, Option<usize>);
pub fn combine(a: SizeHint, b: SizeHint) -> SizeHint {
    let low = a.0.saturating_add(b.0);
    let high = fallible { a.1?.checked_add(b.1?)? };
    (low, high)
}

```

The idea here is that the `combine` function itself is _infallible_: if it returns, it must produce a hint, and it cannot use `?`. But inside that infallible function, there’s a _fallible_ part where `?` is allowed.

(Advance apologies to @strake if this does happen, though at least `TryFrom` will probably stabilize soon.)

---

<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 23, 2018, 8:17am UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/2 "2018-03-23T08:17:27Z")

</div>

I also think that it’s best not to use the `catch` keyword because its meaning would be different in Rust than elsewhere (languages with exceptions). A keyword that signifies that the error propagation is stopped though would be nice.

Some synonyms to catch:

```rust
accept
capture
collect
recover
resolve
take
trap 

```

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [March 23, 2018, 9:23am UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/3 "2018-03-23T09:23:38Z")

</div>

I think the perspectives

- “This is essentially exception handling, but done right, so we should use the accepted terminology for it which people are already familiar with”, and

- “The primary connotation of ‘exception handling’ from other languages is that it is bad, so we should avoid reminding people of it at any cost”

are both valid in their own way, apparently irreconcilable, and we could probably continue bikeshedding on this basis until the End of Time.

(Compounded by the fact that the defining characteristics of what counts as “being exceptions” _also_ varies from person to person.)

My own view is that what we have is manually propagated exceptions, and that using unfamiliar vocabulary (keywords) is a larger cost in terms of the “language strangeness budget” than re-using widely adopted vocabulary in slightly different ways, and that therefore we should use either `catch` or `try` here, but YMMV.

I think it’s notable that other languages “with exceptions” _also_ have very different formulations of the idea amongst themselves, and that they use the usual “exception handling keywords” in wildly different ways, so I don’t think we’d be very much out of line with this; if anything, we’d just be following tradition.

(For instance, Swift uses `try` to mean “this code, unlike other code, may throw exceptions, and they will be propagated”; unlike Java, which uses it to mean “this code, like all other code, may throw exceptions, but here they will be intercepted”.)

---

<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: [March 23, 2018, 9:36am UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/4 "2018-03-23T09:36:06Z")

</div>

> [@glaebhoerl](#):
>
> My own view is that what we have is manually propagated exceptions, and that using unfamiliar vocabulary (keywords) is a larger cost in terms of the “language strangeness budget” than re-using widely adopted vocabulary in slightly different ways, and that therefore we should use either catch or try here, but YMMV.

This is how I see it too. Let me expand a bit. I think that there is a belief -- one that I have shared from time to time -- that it is not helpful to use familiar keywords unless the semantics are a perfect match, the concern being that they will setup an intuition that will lead people astray. I think that is a danger, but it works both ways: those intuitions _also_ help people to understand, particularly in the early days. So it's a question of "how far along will you get before the differences start to matter" and "how damaging is it if you misunderstand for a while".

I'll share an anecdote. I was talking at a conference to [Joe Armstrong](https://en.wikipedia.org/wiki/Joe_Armstrong_(programmer)) and I asked him for his take on Elixir. He was very positive, and said that he was a bit surprised, because he would have expected that using more familiar, Ruby-like syntax would be confusing, since the semantics of Erlang can at times be quite different. But that it seemed that the opposite was true: people preferred the familiar syntax, even when the semantics had changed. (I am paraphrasing, obviously, and any deviance from Joe's beliefs are all my fault.)

I found that insight pretty deep, actually. It's something that I've had kicking around in my brain -- and I know people in this community and elsewhere have told me before -- but somehow it clicked that particular time.

**Rust has a lot of concepts to learn.** If we are going to succeed, it's essential that people can learn them a bit at a time, and that we not throw everything at you at once. I think we should always be on the lookout for places where we can build on intuitions from other languages; it doesn't have to be a 100% match to be useful.

---

<div class="post-metadata">

### Author: ![jsgf](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jsgf/32/703_2.png) [@jsgf](https://internals.rust-lang.org/u/jsgf)
#### Post date: [March 23, 2018, 12:03pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/5 "2018-03-23T12:03:01Z")

</div>

The main concern in my mind is that Rust `catch` is analogous to other languages’ `try` (thing which might fail) rather than `catch` (failure handling).

---

<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: [March 23, 2018, 3:21pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/6 "2018-03-23T15:21:50Z")

</div>

I’ve been a fan of renaming `catch` to `try` for a while- it is much closer to other languages’ use of the terms.

This came up in the “catching functions” thread, and IIRC it was even considered in the original RFC, but was avoided due to confusion with the `try!` macro, which is now no longer really an issue.

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 4:40pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/7 "2018-03-23T16:40:27Z")

</div>

What is the purpose of “catch” in Rust again? I’m having trouble understanding why catch is useful at all given the way ? works and Result, etc. It just seems like and exercise in, “Rust doesn’t do exceptions because everyone agrees they are dumb. Rust does Result\<T,E\> instead and forces user to deal with errors or implicitly propagate with ?; however, we want exceptions like every other language because they are good.”

Which all just sounds like self-contradictory nonsense. If Rust chose (wisely) not to use exceptions like C++/Java/C#, then, why is it now trying to bolt it on? What’s the goal?

---

<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: [March 23, 2018, 4:42pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/8 "2018-03-23T16:42:27Z")

</div>

I too have thought about revisiting this. I do agree with @jsgf that `try` is the keyword I would have “guessed”, not `catch`, even though I also agree with @glaebhoerl that there is a tradition of tweaking exception-related terminology. =)

---

<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: [March 23, 2018, 4:46pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/9 "2018-03-23T16:46:58Z")

</div>

> [@gbutler](#):
>
> What is the purpose of “catch” in Rust again?

You don't always want to jump out of the whole function; I've been a proponent of `catch` for some time because it offers a compelling alternative to combinators like `map`, `and_then`, and friends (and keep in mind that `?` operators on options and results and potentially other things).

Here is an example of some code from the compiler that uses `catch`:

```rust
    let _: io::Result<()> = do catch {
        let mut file =
            pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
        regioncx.dump_graphviz(&mut file)
    };

```

I can't find it now, but recently I was working with some code that did something like:

```rust
let x = something
    .and_then(|x| something_else(x))
    .map(|y| y + 2)
    .and_then(|y| process(y))
    .map(|z| z * 3);

```

such code reads much nicer using `catch`, in my opinion (here I assuming an "ok-wrapping" variant):

```rust
let x = catch {
    let y = something_else(something?)?;
    process(y + 2)? * 3
};

```

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 4:51pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/10 "2018-03-23T16:51:02Z")

</div>

> You don’t always want to jump out of the whole function; I’ve been a proponent of catch for some time because it offers a compelling alternative to combinators like map, and\_then, and friends (and keep in mind that ? operators on options and results and potentially other things).

OK, I think I understand now. Thanks for the clear example. So, it is kind of the equivalent of taking a block of code, breaking it out into it's own function that returns Result\<T,E\> and then putting that call in the code blocks place?

---

<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: [March 23, 2018, 4:53pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/11 "2018-03-23T16:53:23Z")

</div>

Exactly. People tend to dislike exceptions because they introduce non-local control flow, or because they are implemented with unwinding. `catch` does the opposite- it _tightens_ the scope that `?` applies to, using the same mechanisms as function-level `?`.

---

<div class="post-metadata">

### Author: ![steveklabnik](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steveklabnik/32/4524_2.png) [@steveklabnik](https://internals.rust-lang.org/u/steveklabnik)
#### Post date: [March 23, 2018, 5:07pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/12 "2018-03-23T17:07:45Z")

</div>

I was recently writing some code that intermixes `Result` and `Option`. The intent of the code was "If anything goes wrong, at all, then please set this to the empty string.

I ended up with this… monstrosity:

```rust
let base_url = (|| {
            let mut toml_file = File::open(config_path)?;
            toml_file.read_to_string(&mut contents)?;
            let doc = contents.parse::<toml_edit::Document>()?;

            Ok((|| {
                let value = doc["docs"]["base-url"].as_value()?;
                let value = value.as_str()?;
                Some(value.to_string())
            })()
                .ok_or("")?)
        })()
            .unwrap_or_else(|_: Box<::std::error::Error>| String::from(""));

```

(The `rustfmt` here is… yeah also not spectacular)

This uses closures to contain the `?` so I don’t return from the enclosing function. Basically, the error cases here aren’t errors for the caller, so while `?` looks great, and works, I don’t want to jump out of the enclosing function. I want to catch any error and give `String::new`.

with `catch`, this would be

```rust
        let base_url: Result<String, Box<::std::error::Error>> = do catch {
            let mut toml_file = File::open(config_path)?;
            toml_file.read_to_string(&mut contents)?;
            let doc = contents.parse::<toml_edit::Document>()?;

            let value = doc["docs"]["base-url"].as_value()?;
            let value = value.as_str()?;
            Ok(value.to_string())
        };

        let base_url = base_url.unwrap_or(String::new());

```

well, this doesn’t _quite_ work, since `NoneError` doesn’t implement `Error`. I remember reading an issue about this…

anyway I’m not gonna say it’s the _best_ code ever, but that’s the basic idea.

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 5:34pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/13 "2018-03-23T17:34:08Z")

</div>

> [@nikomatsakis](#):
>
> let x = catch { let y = something\_else(something?)?; process(y + 2)? \* 3 };

One thing I don't like about using the "catch" keyword for this is that it doesn't really correspond to what catch does in other languages. Here, it stops auto-propagation of returning a Result and instead assigns what would've been returned as the result of the catch block, but, if no error is returned, then the result of the catch block is the result of the expression. Normally a "catch" corresponds to, "In the event of error, do this other thing instead". This is more like, "In the event of error, make the result the error, otherwise make the result the result".

For that reason, the word, "catch" just doesn't feel quite right. That being said, I'm not sure what would _feel_ better. Some possibilities:

- coalesce
- fuse
- unite
- cohere
- consolidate
- unify
- combine

In other words, a "word" that indicates that the actual result or error that might be returned will be combined/coalesced/unified into the result of the block.

Alternatively, "resultof", so it would be:

```rust
let x = resultof {
    let y = something_else(something?)?;
    process(y + 2)? * 3
};

```

---

<div class="post-metadata">

### Author: ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)
#### Post date: [March 23, 2018, 5:45pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/14 "2018-03-23T17:45:31Z")

</div>

> [@nikomatsakis](#):
>
> ```rust
> let x = something
> .and_then(|x| something_else(x))
> .map(|y| y + 2)
> .and_then(|y| process(y))
> .map(|z| z * 3);
> 
> ```

If we eta-reduce, I think it reads slightly better:

```rust
let x = something
          .and_then(something_else)
          .map(|y| y + 2)
          .and_then(process)
          .map(|z| z * 3);

```

or rustkell:

```rust
let x = do {
    x <- something;
    y <- something_else(x);
    z <- process(y + 2);
    pure(z * 3);
};

```

I think this is pretty optimal readability-wise.

[https://philipnilsson.github.io/Badness10k/escaping-hell-with-monads/](https://philipnilsson.github.io/Badness10k/escaping-hell-with-monads/)

My gripe with `async { .. }`, `catch { .. }` is the lack of generality. Of course, this was discussed (in one of @nikomatsakis's comments) in the RFC that introduced `catch`; and monads would have their problems in Rust (but they would also be massive enablers). I think we should be somewhat careful going forward with adding specialty features for particular monads but `catch` / `try` seems fine. I just want us not to forget about HKTs and do notation before stabilizing 😉

Regarding `try` vs. `catch`, I thought I was in favor of the latter, but I'm coming over to the side of `try` because the trait is called `Try` after all... However "catching any Err values" also makes a lot of sense.

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [March 23, 2018, 6:08pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/15 "2018-03-23T18:08:30Z")

</div>

> [@gbutler](#):
>
> Normally a “catch” corresponds to, “In the event of error, do this other thing instead”.

FWIW the original syntax I proposed in the RFC mimicked the usual `try`-`catch` form more closely: [rfcs/active/0000-trait-based-exception-handling.md at 63a3c4d088374a9f3929acd77cdaa407b6d80e8f · glaebhoerl/rfcs · GitHub](https://github.com/glaebhoerl/rfcs/blob/63a3c4d088374a9f3929acd77cdaa407b6d80e8f/active/0000-trait-based-exception-handling.md#trycatch) (N.B. whenever I used the word "exception" there, I just meant "the `E` component of a `Result<T, E>`")

That would basically be built-in syntax sugar for a `.unwrap_or_else()` on the result of the first block.

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 6:13pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/16 "2018-03-23T18:13:43Z")

</div>

```rust
let x = resultof {
    let y = something_else(something?)?;
    process(y + 2)? * 3
};

```

The more I think about it, the more I would like something like “resultof” instead of “catch” as far as how it reads and feels. My second choice (I think) would be “consolidate”:

```rust
let x = consolidate {
    let y = something_else(something?)?;
    process(y + 2)? * 3
};

```

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 6:20pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/17 "2018-03-23T18:20:04Z")

</div>

Really like the “do” syntax from Haskell.

---

<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: [March 23, 2018, 6:31pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/18 "2018-03-23T18:31:19Z")

</div>

> [@gbutler](#):
>
> Normally a “catch” corresponds to, “In the event of error, do this other thing instead”.

This is why I like `try`: normally, it corresponds to "run this block, and if it throws land here during unwinding." So in Rust, it would mean "run this block, and if it fails stop here."

This is also why I like `Ok`-wrapping: the block is supposed to be the "happy path," and the fact that it can fail is handled entirely by the `try` construct.

---

<div class="post-metadata">

### Author: ![davidtwco](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/davidtwco/32/10027_2.png) [@davidtwco](https://internals.rust-lang.org/u/davidtwco)
#### Post date: [March 23, 2018, 6:41pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/19 "2018-03-23T18:41:15Z")

</div>

I personally prefer keywords such as `do` or `trap`. Particularly `trap` as I think it is sufficiently un-associated with other languages in my mind; seems like a keyword associated with errors and I think it gives an impression of a sort of containment that nicely maps to what this does - it traps any errors from being propagated higher.

I only recently heard about `catch` in reading Rust-related things and I immediately associated it to try catch blocks in other languages and I had to go read the RFC to understand “oh, this makes sense, it’s not like other languages”. I don’t think that familiarity with the word is something beneficial in this case.

---

<div class="post-metadata">

### Author: ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)
#### Post date: [March 23, 2018, 6:45pm UTC](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121/20 "2018-03-23T18:45:39Z")

</div>

> [@davidtwco](#):
>
> I don’t think that familiarity with the word is something beneficial in this case.

Agree!

Also, "trap" sounds pretty good:

```rust
let x = trap {
    let y = something_else(something?)?;
    process(y + 2)? * 3
};

```

But, I still like "resultof" because it is getting the "Result\<T,E\>" of the block assigned to the let variable. Once someone understands that the error propagation mechanism of Rust is Result\<T,E\> "resultof" should sound intuitive (or at least that's my story and I'm stickin' to it) 🙂

That being said, I like "trap" more than "try" or "catch" for exactly the reasons you gave.

[Next page](https://internals.rust-lang.org/t/bikeshed-rename-catch-blocks-to-fallible-blocks/7121.md?page=2)
