# Pre-RFC: Throwing Functions

**URL:** <https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419>\
**Category:** language design\
**Created:** [June 20, 2017, 2:54pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419 "2017-06-20T14:54:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)\
**Post date:** [June 20, 2017, 2:54pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/1 "2017-06-20T14:54:02Z")

</div>

- Feature Name: throwing\_functions
- Start Date: 2017-06-20
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary

Add an annotation to functions that they may “throw” an error type, which changes the function’s return type to `Result<T, E>` where `T` is the functions return type and `E` is the function’s annotated error type. Also add a macro `throw!` to facilitate early return of errors.

# Motivation

Rust’s error handling is on the one hand very powerful, and values correctness and clarity, on the other hand it can be somewhat cumbersome and unergonomic in some cases. This is why error handling has been singled out as part of the ergonomics initiative.

The introduction of the `?` operator and the `Try` trait has made it easier to write functions which propagate errors. With RFC1937, the `?` operator will become even more prevalent.

One downside with the `?` operator is that the positive case, when no error has occurred, still necessitates special handling, since the return value needs to be wrapped in `Ok()`. This is especially cumbersome for functions which return `()`, since instead of simply not specifying a return value, the unsightly `Ok(())` needs to be returned. This is not only aesthetically unfortunate, but also confusing to new users.

Here’s an example of the necessity of wrapping the return value in `Ok` and the `Ok(())` return value in particular:

```rust
use std::path::Path;
use std::io::{self, Read};
use std::fs::File;

fn read_file(path: &Path) -> Result<String, io::Error> {
  let mut buffer = String::new();
  let file = File::open(path)?;
  file.read_to_string(&mut buffer)?;
  Ok(buffer)
}

fn main() -> Result<(), io::Error> {
  let content = read_file(&Path::new("test.txt"))?;
  println!("{}", content);
  Ok(())
}

```

# Detailed design

The syntax of function definitions, both for free functions, inherent impls, and functions in trait definitions and implementations will be extended with the `throws` contextual keyword and a type, which must appear after the function’s return type and before any `where` clauses.

The return type of any function which is annotated with `throws` becomes `Result<T, E>` where `T` is the function’s return type and `E` is the error type which appears after the `throws` keyword.

The function body must evaluate to `T` and any early return from the function must also evaluate to `T`. It is not possible to return a `Result<T, E>` from the function body. If the `?` is used within such a function, unless it is used within a `catch` block, it will operate in the same way as if it were used in a regular function with return type `Result<T, E>`.

For example:

```rust
use std::path::Path;
use std::io::{self, Read};
use std::fs::File;

fn read_file(path: &Path) -> String throws io::Error {
  let mut buffer = String::new();
  let file = File::open(path)?;
  file.read_to_string(&mut buffer)?;
  buffer
}

fn main() throws io::Error {
  let content = read_file(&Path::new("test.txt"))?;
  println!("{}", content);
}

```

## Forcing an error return

One particular case where this design is till somewhat cumbersome is in returning an error from a function directly, this can be solved by adding a `throw!($expr)` macro to the prelude, which expands to `Err($expr)?`. While it would be nicer to have a `throw` keyword, similar to `return`, since `throw` is currently not a reserved keyword, this would be a breaking change, and probably not acceptable in Rust \< 2.0.

For example,

```rust
fn main() throws MyError {
  let content = read_file(&Path::new("test.txt"))?;
  match &content {
    "ok" => println!("Everything is ok!"),
    _ => throw!(MyError::InvalidFileContent),
  };
};

```

# How We Teach This

This feature should be taught as part of Rust’s error handling story, in particular since it is closely tied to the `?` operator, it should be taught alongside it. In particular the connection between this and the `Result` type should be made explicit. It is important to emphasize that this is not an exception mechanism and that thrown errors do not automatically propagate up the callstack, like it might be expected from other other languages, and as is the case with panics.

A major benefit of this feature is that in a pre-rigorous stage, users can be effective in handling errors in Rust through the `?` operator, the `throws` annotation and the `throw!` macro, even if they are not familiar with algebraic data types or `Result` return types.

# Drawbacks

The major downside of this feature is that it makes the function signature somewhat more opaque. It is not immediately clear that the return value of the function is a `Result`, in fact the `Result` type does not appear in the function signature at all. This can appear this feature appear to be somewhat magical. It may hide the affect that other features of the `Result` type, such as monadic combinators or its implementations for `FromIterator` may be used with throwing functions.

# Alternatives

- An alternative design would be to automatically coerce the return value of any function which returns a `Result` into a `Result::Ok` value unless it is already a result. While this makes the type of the function more clear, it introduces a lot of ambiguity around the return value of the function. For example, if the return value of the function is `Result<Result<T, E>, E>`, what would a return value of `Err(foo)` mean?

- Use a keyword for `throw` instead of a macro. While this would be aesthetically preferrable, it is probably not possible due to backward compatibility issues.

- Skip the `throw!` macro all together. This would mean that users would still have to learn about the `Err` variant constructor in the pre-rigorous stage.

- Do nothing, which leaves the status quo of the somewhat unsightly `Ok(())` and friends.

# Unresolved questions

- What is the appropriate name for this feature? This has previously been called “checked exceptions”, but this terminology brings with it a lot of baggage, and also is not correct, since this is in fact not an exception mechanism.

- Should this mechanism somehow be extended to other types which can be used with the `?` operator?

- This feature does not have a strightforward desugaring to Rust syntax, like the `?` operator does for example, are there any challenges with implementing this design?

---

<div class="post-metadata">

**Author:** ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)\
**Post date:** [June 20, 2017, 2:56pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/2 "2017-06-20T14:56:55Z")

</div>

There’s some issue with the markdown formatting here, it renders fine both locally and on GitHub, and I can’t see anything that’s wrong.

EDIT: never mind, seems like Discuss doesn’t like fenced code blocks.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [June 20, 2017, 5:00pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/3 "2017-06-20T17:00:10Z")

</div>

I’d definitely would like to see a solution for functions returning `Ok(())`.

However, I’m worried that calling it _throwing_ (and using syntax similar to Java’s checked exceptions) can give wrong expectations to users coming to Rust (e.g. the returned value is still a `Result`, and “throwing” doesn’t unwind the stack unpredictably).

`Result` as an explicit function return type is not too bad. It’s explicit. It can be aliased to avoid typing complex types repeatedly.

---

<div class="post-metadata">

**Author:** ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)\
**Post date:** [June 20, 2017, 5:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/4 "2017-06-20T17:03:59Z")

</div>

I agree that `throw` and `throws` is a bit problematic, since it implies that something should be caught, which isn’t really the case here. On the other hand, Rust is already going down this road somewhat with the planned addition of `catch`. I tried to come up with a less overloaded term, but I was unable to come up with anything else which seemed reasonable.

---

<div class="post-metadata">

**Author:** ![jmst](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jmst](https://internals.rust-lang.org/u/jmst)\
**Post date:** [June 20, 2017, 5:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/5 "2017-06-20T17:31:40Z")

</div>

I think the major drawback is adding new syntax just for the convenience of omitting Ok() in returns, which may or may not be worth it.

There’s also an alternative syntax:

```rust
ok fn read_file(path: &Path) -> Result<String, io::Error> {

```

where “ok” (could bikeshed this to some other string) enables the Ok desugaring.

The advantage of this syntax is that the return type is explicit and it parallels the async function syntax assuming the C#/TypeScript syntax is adopted in Rust (Future and Result are both monads and thus async/await and ok/? are analogous), the disadvantage is that it is less similar to the C++/Java throw declaration syntax.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 20, 2017, 5:41pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/6 "2017-06-20T17:41:51Z")

</div>

> [@jmst](#):
>
> The advantage of this syntax is that the return type is explicit

Which also generates another advantage, it works with all types that implement [`Try`](https://github.com/rust-lang/rfcs/blob/master/text/1859-try-trait.md#desugaring-and-the-try-trait). Basically it would implicitly wrap any returned value via `Try::from_ok`. That to me seems a much more useful route to go than forcing it to be `Result` specific.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [June 20, 2017, 5:46pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/7 "2017-06-20T17:46:24Z")

</div>

> [@jnicklas](#):
>
> An alternative design would be to automatically coerce the return value of any function which returns a Result into a Result::Ok value unless it is already a result. While this makes the type of the function more clear, it introduces a lot of ambiguity around the return value of the function. For example, if the return value of the function is Result\<Result\<T, E\>, E\>, what would a return value of Err(foo) mean?

We already intended to do auto-wrapping for `catch` blocks ([#41414](https://github.com/rust-lang/rust/issues/41414)). This alternative is a more natural extension than the main Pre-RFC.

I'd expect `Err(foo)` returns the outer Result, since you could always use `Ok(Err(foo))` to make the inner Result.

---

<div class="post-metadata">

**Author:** ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)\
**Post date:** [June 20, 2017, 6:20pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/8 "2017-06-20T18:20:39Z")

</div>

> [@jnicklas](#):
>
> if the return value of [a] function is `Result<Result<T, E>, E>`,

When would it actually make sense to do this? In other words, is this a scenario we should actually worry about? (I recognize that the language has to do _something_, but if we don't think it will come up, it could just do whatever is convenient.)

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [June 20, 2017, 11:08pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/9 "2017-06-20T23:08:30Z")

</div>

For just auto-wrapped returns it may be possible to require _no_ new syntax at all. Currently returning a result value without an `Ok`/`Err` wrapper is a type error, so allowing auto-wrapping under a condition that the value wouldn’t type-check otherwise should be perfectly backwards-compatible.

e.g.

```rust
fn foo<T,E>() -> Result<T,E> {
    …
   return x;
}

```

It could work something like that:

1. Is type of `x` a `Result<T,E>`? Return `x` as-is.
2. Is type of `x` = `T`, but not `E`? Return `Ok(x)`
3. Is type of `x` = `E`, but not `T`? Return `Err(x)`
4. Error - ambiguous (could be either `T` or `E`, e.g. `-> Result<u32, u32>` & `return 1`)

---

<div class="post-metadata">

**Author:** ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)\
**Post date:** [June 21, 2017, 7:49am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/10 "2017-06-21T07:49:38Z")

</div>

As far as I can see it, if we want to get rid of `Ok(())`, there are four possible solutions:

1. A special handling of `Result` in the compiler where values are coerced if possible (as proposed by @kornel)

2. A trait based solution, maybe using `From::from` to implicitly coerce returned values. It could use a specific trait for this, let’s say `ReturnFrom` or something.

3. Annotate the function somehow making it explicit that a conversion will happen, but keep the return type as `Result<T, E>`

4. Annotate the function with a separate error type (this pre-RFC proposal)

* * *

I find (1) problematic, because it is unexpected that this would work in the first place. Why would returning the wrong type from a function suddenly work? And why only for certain functions? I also find the coherence issue extremely problematic. Remember that it’s not enough that `T` and `E` aren’t identical, but it must be the case that they _couldn’t_ be identical. For example, the following would work:

```rust
fn foo() -> Result<&'static str, u32> {
    "test"
}

```

But the following wouldn’t:

```rust
fn foo<T>() -> Result<T, u32> {
    T::blah() // returns `T`
}

```

Because the compiler cannot be sure that `T` isn’t u32 and in that case the return value of the function would be ambiguous.

I think this would lead to very unintuitive behaviour where this feature _sometimes_ works, due to reasons which aren’t very intuitive.

* * *

The second solution (2) is problematic because of the same coherence reasons as (1). It is also not feasible to ever stabilize this trait, since it would open up the language to all kinds of implicit coercions, which could cause all kinds of coherence problems, and implicit behaviour that users are not expecting. I’m not sure, but it also seems problematic to me to even write such a trait and a sensible implementation for `Result`, given today’s coherence rules. I think such a trait would require trait bound inequalities, which we don’t currently have, and which are not even anywhere near being implemented.

Personally I find both of these options far _more_ magical than using an annotation.

* * *

I think both (3) and (4) have their pros and cons.

With either of these solutions, if we want to avoid the coherence problems of (1) and (2), it should not be possible to return a `Result<T, E>` type, instead the unwrapped `T` type must be returned, with `E` only being propagated via the `?` operator.

It’s notable that C# and TypeScript, which are statically typed languages that implement async/await which is superficially similar to this feature, have both chosen the first option. They have both an `async` annotation on the function, yet the return type is `Task<T>` or `Promise<T>` respectively. So from a prior-art perspective, option (3) seems to be more common.

However, I personally find (4) much more attractive. I think being able to omit `Result` is actually an _advantage_ as I laid out in the pre-RFC text.

I really like the fact that when transitioning from `fn foo() -> T` to `fn foo() -> T throws E` the type after `->` is always what the function body evaluates to. It feels like the wrapping that is happening is much less magical and odd that way.

I’ve also been unable to come up with a syntax for (3) which I find acceptable. The suggestion above to use `ok fn foo()` seems like it could be problematic to parse to me, since `ok` is not a reserved keyword, but I could be wrong, I don’t really know how the parser works. I also find it a bit too subtle. Since this annotation has a rather profound effect on the function body. It also seems quite disconnected from the return type of the function, which is what the annotation affects, so it feels like it should be visually closer to it.

---

<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:** [June 21, 2017, 8:11am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/11 "2017-06-21T08:11:50Z")

</div>

The `throws` syntax possibility was mentioned back in [https://github.com/rust-lang/rfcs/blob/master/text/0243-trait-based-exception-handling.md#throw-and-throws](https://github.com/rust-lang/rfcs/blob/master/text/0243-trait-based-exception-handling.md#throw-and-throws). I’m not a big fan, since it seems to disadvantage `Option` and `Poll`.

The current [direction](https://github.com/rust-lang/rust/issues/41414#issuecomment-298096222) from the lang team here is that function and catch results should automatically be wrapped using [`Try::from_ok`](https://doc.rust-lang.org/nightly/std/ops/trait.Try.html#tymethod.from_ok) if they’re not already the correct type. That way changing from `-> T` to `-> io::Result<T>` will “just work”\*. I’m behind on writing the RFC, sorry 😞 (Personally I’ve stopped calling this a coercion, since it’s location-specific and non-transitive, unlike the existing coercions.)

My latest strawman for “mark the functions where the different behaviour is desired” syntax is `fn blah()? -> Option<i32> { 4 }`, trying to mirror how the call (`let x = blah()?;`) ends up looking. I’m torn; explicit marking makes some things easier, but not having to do anything would be awfully nice.

I would like to get a `throw e;` syntax at some point, but near term it’ll probably be spelled `Err(e)?`. Adding keywords is hard right now, as `throw(4)` is a valid function call that we can’t break.

​\* Modulo producing return values via methods on traits left to be inferred, like `Default:default()` ​

---

<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:** [June 21, 2017, 8:42am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/12 "2017-06-21T08:42:04Z")

</div>

To me, this seems like one of those ergonomics issues where the problem is not how many characters you need to type or where you need to type them, but the fact that you need to remember to type anything at all. So I don’t understand any of the suggestions that we replace ‘Ok()’ at the “return site” with some other annotation like an ‘ok’ or ‘?’ or ‘throws’ in the function signature. Not only does that not solve the problem, but it’s introducing multiple equally good ways of writing the same thing, adding unnecessary implementation details to the function’s signature, and in the case of ‘throws’ potentially misleading a ton of newcomers from other languages.

When I originally heard about this problem, it sounded like it was mostly about cases like ‘Ok(())’ where you’re “returning nothing”. For that case we could potentially have a special case for “empty” types like (). But now it sounds like ‘Ok(buffer)’ is also part of the concern, in which case it seems obvious that the only feasible solution that might actually solve this problem without creating new equally bad problems is “if a return value doesn’t type check, try adding Ok() before giving up”. So +1 for using Try::from\_ok.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [June 21, 2017, 10:48am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/13 "2017-06-21T10:48:41Z")

</div>

> [@jnicklas](#):
>
> But the following wouldn't:
> 
> fn foo\<T\>() -\> Result\<T, u32\> { T::blah() // returns `T` }

There's no ambiguity in this case, because Rust doesn't do [SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error). "`T` that may be `u32`" and `u32` [are always distinct types in Rust already](https://is.gd/WCgvMz):

> | t | ^ expected u32, found type parameter | = note: expected type `u32` found type `T`

---

<div class="post-metadata">

**Author:** ![FlorentBecker](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/florentbecker/32/2685_2.png) [@FlorentBecker](https://internals.rust-lang.org/u/FlorentBecker)\
**Post date:** [June 21, 2017, 1:48pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/14 "2017-06-21T13:48:17Z")

</div>

From a PR point of view, I find that spelling `Ok(())` in functions which return `Result<(),E>` is actually a good thing. It reads as: “and if we get here, then everything has worked ok”, which helps reinforce the notion that errors have been thought about and treated, and helps distinguish Rust from the perceived problems of exception-based solutions. I for one, am _proud_ of our **glorious** Ok(()).

My counter-proposal is to simply define 👌 as an alias for `Ok(())`.

I also don’t see any of the proposals as a win for teaching Rust. For instance, consider a case where a bunch of Result\<T,E\> gets stored in a data structure instead of T values, ie where a non-monadic function like `map()` has been used instead of a monadic one. In this case, I think it is easier to make sense of this (failing) example than what you get with `throws`.

```rust
fn faillible_seventeen(i: u32) -> Result<u32, SomeErrorType> {
    Ok(17)
}

fn main() {
    let v = vec![1,2,3,4];
    let vv = v.map(faillible_seventeen);
    assert_eq!(vv, [17,17,17,17]); // This won't type-check.
    println!(success)
}

```

With throws, the code looks like the following, and it is harder to grasp the situation with the spurious `Ok()` around each 17.

```rust
fn faillible_seventeen(i: u32) -> u32 throws SomeErrorType {
    17
}

fn main() {
    let v = vec![1,2,3,4];
    let vv = v.map(faillible_seventeen);
    assert_eq!(vv, [17,17,17,17]); // This won't type-check
    println!(success)
}

```

In particular, the second version gives the false impression that the following is not possible:

```rust
fn main() {
    let v = vec![1,2,3,4];
    let vv = v.flat_map(faillible_seventeen); // We keep the successful seventeens
    assert_eq!(vv, [17,17,17,17]); 
    println!(success)
}

```

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 21, 2017, 2:02pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/15 "2017-06-21T14:02:06Z")

</div>

An example of the sort of function in which (I believe) `Ok(())` is just pure noise:

```rust
fn write_multihash(w: &mut io::Write, multihash: &MultiHash) -> io::Result<()> {
    w.write_usize_varint(multihash.code())?;
    w.write_usize_varint(multihash.len())?;
    w.write_all(multihash.digest())?;
    Ok(())
}

```

I also find this example really bad because there is an alternative way to write it and I’m like 70:30 on which way is better

```rust
fn write_multihash(w: &mut io::Write, multihash: &MultiHash) -> io::Result<()> {
    w.write_usize_varint(multihash.code())?;
    w.write_usize_varint(multihash.len())?;
    w.write_all(multihash.digest())
}

```

I’d really love to be able to write this as if it were a normal return-value-less function and have the `Ok(())` implied (the first example minus the last line).

---

<div class="post-metadata">

**Author:** ![est31](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/est31/32/2551_2.png) [@est31](https://internals.rust-lang.org/u/est31)\
**Post date:** [June 22, 2017, 8:58am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/16 "2017-06-22T08:58:38Z")

</div>

I always have been glad that Rust didn’t have special operators for stuff like this, but instead everything was a convention instead. Similar for constructors.

However, I hugely dislike converting `X` into `Ok(X)` or into `Ok(Some(X))` without any notice, as there is this popular pattern of `fn foo() -> Result<(),()> { bar() }`. With the proposed implicit coercion, that would be ambiguous, bar could return either a `Result<(),()>`, or `()`. I would really really not like such ambiguities to appear in the language, that seems like a big bug to me. Also, unless you make the coercion work _on function bodies only_ (which is a novelty, and would make the language harder to learn) is this ugliness with that you now have to allow stuff like `let x: Option<Option<i32>> = 4;`.

Instead I would prefer having some explicit syntax, where we opt in to a conversion, and where the `fn foo() -> Result<T,E> { bar() }` case above is forbidden (because it expects either `T` or `E` but not the `Result`). Which syntax we end up, whether its `fn blah()? -> Option<i32>` like @scottmcm proposed, or the `throws` syntax, I don’t really care, as long as its explicit and the conversion is a must-do one.

---

<div class="post-metadata">

**Author:** ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)\
**Post date:** [June 22, 2017, 9:03am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/17 "2017-06-22T09:03:53Z")

</div>

I agree completely. The function body should evaluate to `T` or to `Result<T, E>`, for _both_ to be allowed would be very confusing.

---

<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:** [June 22, 2017, 10:39am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/18 "2017-06-22T10:39:34Z")

</div>

@est31 Thanks for substantiating the feeling I’ve had that something’s fishy with the "just coerce to `Ok`" approach, but couldn’t articulate 🙂

I think the idea to use `?` instead of `throws` in the signature would make sense if we left off the "`Try` type" in the same way as the `throws` proposal does. Because in that case, given `fn blah()? -> i32 { 42 }`, the intuition would be that the type of `blah()?` as an expression _is_ precisely `i32`, which is kinda neat. But it unfortunately doesn’t seem like it can work, because it doesn’t leave anywhere to specify what the error type is.

Other things:

- Someone suggested that a drawback of `throws` is that it would only work with `Result` and not other `Try` types, but I don’t think this has to be the case. In principle, the body of a `throws` function would _never_ mention the variants of the `Try` type it’s returning, they would only be created through `?` for errors and wrapping for ‘successes’. So in theory it could return any `Try` type we choose; but even if it returns `Result` specifically, `Try` itself allows it to be converted to a different one. If I’m not missing something, then `fn foo() -> X throws Y` could desugar into any of `fn foo() -> Result<X, Y>`, `fn foo() -> impl Try<Ok=X, Err=Y>` (in which case the only thing the caller could do with it is `?` or `.try()`), or `fn foo<Res: Try<Ok=X, Err=Y>() -> Res` (in which case `foo()` would desugar to use `Try::from_ok()` and `Try::from_err()` at its exit points to convert to whichever type the caller requests), and they all seem like workable approaches (though I haven’t worked it out in detail). I’m not sure which one might be best.

- This is of course related to how `catch` should work. I’m of the opinion that `catch` should just always `Ok`-wrap (or `Some`-wrap, etc.) its result, as in the original RFC, but I haven’t had time to read the GitHub thread about this.

- This also seems related to the design work around async/await, where `#[async]` would implicitly wrap a function’s written return type in a `Future` in a similar way to how `throws` would wrap it in a `Result` or `Try`.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [June 22, 2017, 11:39am UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/19 "2017-06-22T11:39:33Z")

</div>

```rust
fn foo() -> X throws Y ==> fn foo() -> impl Try<Ok=X, Err=Y>

```

That is an interesting variant that I didn’t consider at all. I actually quite like it.

* * *

I’m also on the wagon that for a given function it should either _always_ wrap its return values (whether an implicit or explicit return) in a `Try::Ok` variant, or _never_ wrap them. Using the `throws` syntax and given `fn bar() -> Result<(), ()>` that would mean either of

```rust
fn foo() -> Result<(), ()> { bar() }
fn foo() -> () throws () { bar()? }

```

would work, but

```rust
fn foo() -> () throws () { bar() }

```

would give something like

```rust
error[E0308]: mismatched types
  |
2 | fn foo() -> () throws () { bar() }
  | ^^^^^ expected (), found enum `std::result::Result`
  |
  = note: expected type `()`
             found type `std::result::Result<(), ()>`

```

possibly with some help text more specific to `throws` functions than the normal help.

One downside mentioned in the OP that I haven’t seen discussed is that it means you can’t use a normal return to return a `Try::Err` variant from the function. Is there any way to make that more ergonomic than having a macro expanding to `Err(...)?` ?

---

<div class="post-metadata">

**Author:** ![bugaevc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bugaevc/32/13651_2.png) [@bugaevc](https://internals.rust-lang.org/u/bugaevc)\
**Post date:** [June 22, 2017, 7:10pm UTC](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419/20 "2017-06-22T19:10:18Z")

</div>

Why don’t you just write

```rust
fn foo() -> Result<()> { catch {
    stuff_that_can_fail()?;
    stuff_that_cannot();
    // no Ok(()) necessary
}}

```

[Next page](https://internals.rust-lang.org/t/pre-rfc-throwing-functions/5419.md?page=2)
