# Panic!("{}") shouldn't compile

**URL:** <https://internals.rust-lang.org/t/panic-shouldnt-compile/1851>\
**Category:** libs\
**Created:** [April 8, 2015, 11:32pm UTC](https://internals.rust-lang.org/t/panic-shouldnt-compile/1851 "2015-04-08T23:32:05Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![ryanprichard](https://avatars.discourse-cdn.com/v4/letter/r/73ab20/32.png) [@ryanprichard](https://internals.rust-lang.org/u/ryanprichard)\
**Post date:** [April 8, 2015, 11:32pm UTC](https://internals.rust-lang.org/t/panic-shouldnt-compile/1851/1 "2015-04-08T23:32:05Z")

</div>

I thought I’d post this here in hopes of getting more discussion than I’ve seen on [issue #22932](https://github.com/rust-lang/rust/issues/22932).

# Problem

The `panic!` macro is currently overloaded with a single-argument version that accepts `Any` and a multiple-argument version that accepts the same arguments as `format_args!`. This has a few consequences:

- `panic!("{}")` compiles, but it looks like a broken format.
- `assert!(some_boolean_expression, true)` also compiles, but it’s not doing the same thing as `assert_eq!`. This actually [happened](https://github.com/rust-lang/rust/blob/e64670888a2839ba75237b1934c440c4c319b1bb/src/libstd/num/mod.rs#L1636) in the Rust repository. I suspect this kind of typo can’t do that much harm.
- `panic!("message")` is slightly more bloated than it could be. libcore has a single-argument `panic!` that roughly expands to `panicking::panic(&("message", file!(), line!())`. The libstd version is roughly `rt::begin_unwind("message", &(file!(), line!())`. On x86\_64, I [measured](https://gist.github.com/rprichard/f0528270cd2f65ded875) the overhead as 52 bytes for libcore vs 67 bytes for libstd.
- `panic!("x")` and `panic!("x{}", 42)` pass different types of values to `JoinHandle::join()` – `&str` and `String`, respectively.

The vast majority of `panic!` calls I see in the Rust repository are passing a string literal or formatting arguments.

# Proposal

Given that, I propose that we split `panic!` into two macros:

- `panic_any!` which accepts a single argument of `Any` type.
- `panic!` which only accepts formatting arguments.

To keep the code size of `panic!` minimal, we add a new macro, `format_args_literal!`. `format_args_literal!` expands to a string literal rather than an `Arguments` value, and it only accepts a single string literal argument. (Equivalently, it accepts exactly the same inputs as `format_args!`, but only single-argument formats can be converted to a literal.) `format_args_literal!` could also be used to [optimize `println!` et al](https://github.com/rust-lang/rust/pull/22335).

Multiple-argument `assert!` would always take formatting arguments. If any existing `assert!` calls are passing non-string panic values, they would need to be rewritten using `panic_any!`.

I’m not sure what type `panic!("message")` would pass to `JoinHandle::join()`. If the overloaded single-argument `panic!` were strictly a call site size optimization, then perhaps it should pass the type `String` for consistency.

This is a breaking change. It might be too late for 1.0. It seems hard to fix later.

# Alternatives

1. We could add a `panic_fmt!` macro that accepts formatting arguments. We could use the same `format_args_literal!` optimization with it, making it OK to use almost everywhere that `panic!` is used today. I’m unfavorable towards this alternative, because almost all `panic!` calls use formatting arguments. Passing an `Any` value seems to be the exception.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:24am UTC](https://internals.rust-lang.org/t/panic-shouldnt-compile/1851/2 "2019-03-25T08:24:14Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
