# Is it possible to have a better .expect() function that accept formatted literials?

**URL:** <https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789>\
**Category:** Uncategorized\
**Created:** [December 3, 2025, 3:17am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789 "2025-12-03T03:17:48Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Neutron3529](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/neutron3529/32/6976_2.png) [@Neutron3529](https://internals.rust-lang.org/u/Neutron3529)\
**Post date:** [December 3, 2025, 3:17am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/1 "2025-12-03T03:17:48Z")

</div>

TL;DR Is there some better syntax to replace the verbose and annoying `result.unwrap_or_else(|err|panic!("formatted string with error {err} and more infos"))`? If postfix is the solution, is it possible to define postfix macros only on struct/trait objects?

* * *

Currently I found it difficult to replace `.unwrap()` with `.expect("Reason")` since "Reason" usually contains valuables variable to be formatted.

When I ask how to write `.expect` with variables formatted, AI told me either using a verbose pattern, such as `unwrap_or_else(|_|panic!(...))`, or creating a &str with `.expect(&format!(...))`, which will facing the penalty that each time we called the function, a String will be formatted no matter whether the result is Ok or Err.

It seems that, a postfix macro might helpful, since we could write something like

```rust
foo.expect!("Reason")

```

which could format all the data we need.

I have searched for several posts of postfix macros, most of the worries are talking about "what to expand". If we limit the postfix macros to trait/struct only, then what to expand is obvious. And for macros that will expand a lot of things, perhaps a postfix will confuse users who read it.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [December 3, 2025, 11:19am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/2 "2025-12-03T11:19:44Z")

</div>

Postfix macros that operate on a specific type are much harder than those who work generically, since they require access to type information, something macros currently cannot access, and letting them access will require a major re-architecture of the compiler.

For this reason, [the current open RFC on postfix macros](https://github.com/rust-lang/rfcs/pull/2442) only proposed type-agnostic macros.

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [December 3, 2025, 7:36pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/3 "2025-12-03T19:36:05Z")

</div>

I realize that postfix is often more convenient, but you could always write a normal macro:

```rust
expect!(foo.unwrap(), "didn't work :( (bar={bar})");

```

which at least to me actually reads better than the method `expect`:

```rust
expect(what_i_expect_to_happen, didnt_happen)

```

rather than

```rust
what_i_expect_to_happen.expect(didnt_happen) 

```

which raises the common question as to how exactly `didnt_happen` should be phrased to make the most sense.

* * *

We do also have a way to represent a lazily formatted string: `format_args!` and `Arguments`. If `expect` could be generalized from taking `&str` to `&dyn Display` (or `&impl Display`) or some more specific trait, that would take care of most of the use cases of the `unwrap_or_else(|| panic!(...))` pattern. That said, it's probably not exactly a priority to make it more convenient to panic on errors.

---

<div class="post-metadata">

**Author:** ![zirconium-n](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zirconium-n/32/9078_2.png) [@zirconium-n](https://internals.rust-lang.org/u/zirconium-n)\
**Post date:** [December 4, 2025, 2:59am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/4 "2025-12-04T02:59:38Z")

</div>

I prefer write `let Ok(val) = result else { panic!("...") }` when applicable. Not usable in chain method call though.

---

<div class="post-metadata">

**Author:** ![ekuber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ekuber/32/1646_2.png) [@ekuber](https://internals.rust-lang.org/u/ekuber)\
**Post date:** [December 4, 2025, 5:24pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/5 "2025-12-04T17:24:04Z")

</div>

The only issue I have with let-else is that I generally do want the contents of the `Err` for the panic string, which leads me to have to fall-back to `match`:

```rust
let val = match foo {
    Ok(val) => val,
    Err(err) => panic!("error: {err:?}"),
};

```

This not _terrible_, but makes me miss let-else 🙂

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [December 4, 2025, 5:40pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/6 "2025-12-04T17:40:23Z")

</div>

Cursed alternative (typed directly into forum):

```rust
let Ok(value) = foo.map_err::<Infallible>(|e| panic!("{e}"));

```

I forget if this exhaustive matching made it into stable yet.

---

<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:** [December 4, 2025, 5:40pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/7 "2025-12-04T17:40:59Z")

</div>

> [@ekuber](#):
>
> This not _terrible_, but makes me miss let-else 🙂

If we were going to do something for this, I think it's this: ["else match" Extending Conditional Syntax - #8 by scottmcm](https://internals.rust-lang.org/t/else-match-extending-conditional-syntax/23780/8)

But it would need someone to analyze the frequency and prevalence at which that would both be applicable and not just be `.unwrap_or_else(|e| panic!("error: {e:?}"))`.

---

<div class="post-metadata">

**Author:** ![ekuber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ekuber/32/1646_2.png) [@ekuber](https://internals.rust-lang.org/u/ekuber)\
**Post date:** [December 4, 2025, 5:51pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/8 "2025-12-04T17:51:38Z")

</div>

```rust
let Ok(value) = foo.map_err::<!>(|e| panic!("{e}"));

```

❗

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [December 4, 2025, 6:15pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/9 "2025-12-04T18:15:29Z")

</div>

You don't even need the `::<!>`:

```rust
let Ok(value) = foo.map_err(|e| panic!("{e}"));

```

And this compiles on stable!

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [December 4, 2025, 6:28pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/10 "2025-12-04T18:28:07Z")

</div>

…but is any of this better than `unwrap_or_else`? Not really.

---

<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:** [December 5, 2025, 2:48am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/11 "2025-12-05T02:48:48Z")

</div>

If `.expect()` took `impl Display` argument, then you could have `x.expect(format_args!("{z}"))` that wouldn't need to heap-allocate anything upfront.

It's still doable with an extension trait.

---

<div class="post-metadata">

**Author:** ![gdennie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gdennie/32/8328_2.png) [@gdennie](https://internals.rust-lang.org/u/gdennie)\
**Post date:** [December 6, 2025, 5:14am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/12 "2025-12-06T05:14:58Z")

</div>

Why not create a macro to embody the `unwrap_or_else` usage pattern. The elimination of such replication is what a prelude of declarative macros is for.

Good luck.

---

<div class="post-metadata">

**Author:** ![Neutron3529](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/neutron3529/32/6976_2.png) [@Neutron3529](https://internals.rust-lang.org/u/Neutron3529)\
**Post date:** [December 6, 2025, 1:28pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/13 "2025-12-06T13:28:43Z")

</div>

Issues occurs when you have a really long chain. This at least requires a postfix macro.

In case you write a chain, you can understand what happens easily:

```rust
some_thing
    .become_another_thing()
    .and_do_some_work()
    .finally_become_a_result()

```

If you want to write macros, things will be harder:

```rust
unwrap!(//what to unwrap?
   some_thing
    .become_another_thing()
    .and_do_some_work()
    .finally_become_a_result()
, panic!("error occurs") //which macro accepts this panic? Am I put the panic! into the wrong place?
).in_case_you_want_to_do_more_things()

```

There are various ways to write equivlent code, but I’m trying to find a simple one.

---

<div class="post-metadata">

**Author:** ![gdennie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gdennie/32/8328_2.png) [@gdennie](https://internals.rust-lang.org/u/gdennie)\
**Post date:** [December 6, 2025, 3:02pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/14 "2025-12-06T15:02:57Z")

</div>

My immediate idea is to employ a suitable wrapper function or method such as would be required to invoke a lambda. This treatment could be generalized by a trait.

```rust
...
do_something()
.wrapper1(|x| ... panic!(...)...)
.wrapper1(do_code_rewrite!(x))
.do_some_more_thing()
...

```

---

<div class="post-metadata">

**Author:** ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)\
**Post date:** [December 6, 2025, 8:57pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/15 "2025-12-06T20:57:09Z")

</div>

If macro aliases were a thing and expect accepted `impl Display`, user may have aliased `format_args!` to `fa!` and used like `.expect(fa!(...))`. Of course such alias won't make it to the std

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [December 6, 2025, 9:38pm UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/16 "2025-12-06T21:38:48Z")

</div>

> [@Ddystopia](#):
>
> If macro aliases were a thing

But... they are a thing!

```rust
use format_args as fa;

fn main() {
    fa!("abc {}", 123);
}

```

---

<div class="post-metadata">

**Author:** ![ais523](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@ais523](https://internals.rust-lang.org/u/ais523)\
**Post date:** [December 7, 2025, 4:30am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/17 "2025-12-07T04:30:13Z")

</div>

This makes me think that the correct solution here is to add a new method that's a hybrid of `map_err` and `into_ok`:

```rust
let value = foo.into_ok_or(|e| panic!("{e}"));

```

Basically `unwrap_or_else` but where the closure's return type is `Into<!>` rather than `T`. I don't tihnk this does anything that `unwrap_or_else` can't do, but it's more readable.

---

<div class="post-metadata">

**Author:** ![DragonDev1906](https://avatars.discourse-cdn.com/v4/letter/d/e68b1a/32.png) [@DragonDev1906](https://internals.rust-lang.org/u/DragonDev1906)\
**Post date:** [December 8, 2025, 9:47am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/18 "2025-12-08T09:47:04Z")

</div>

This already works today. I can't think of a realistic expression that returns `Into<!>` instead of `!`. So I'm not sure where the "it's more readable" comes from.

```rust
let value = res.unwrap_or_else(|e| panic!("{e}"));

```

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=5e808cf26ca91121f4113fdd5e2693e3)**
>
> A browser interface to the Rust compiler to experiment with the language

---

<div class="post-metadata">

**Author:** ![ais523](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@ais523](https://internals.rust-lang.org/u/ais523)\
**Post date:** [December 8, 2025, 10:03am UTC](https://internals.rust-lang.org/t/is-it-possible-to-have-a-better-expect-function-that-accept-formatted-literials/23789/19 "2025-12-08T10:03:01Z")

</div>

The name: `into_ok_or` is a much clearer name for what's going on than `unwrap_or_else` (which normally expects the closure to return a value).
