I thought I’d post this here in hopes of getting more discussion than I’ve seen on issue #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 asassert_eq!
. This actually happened 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-argumentpanic!
that roughly expands topanicking::panic(&("message", file!(), line!())
. The libstd version is roughlyrt::begin_unwind("message", &(file!(), line!())
. On x86_64, I measured the overhead as 52 bytes for libcore vs 67 bytes for libstd. -
panic!("x")
andpanic!("x{}", 42)
pass different types of values toJoinHandle::join()
–&str
andString
, 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 ofAny
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.
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
- We could add a
panic_fmt!
macro that accepts formatting arguments. We could use the sameformat_args_literal!
optimization with it, making it OK to use almost everywhere thatpanic!
is used today. I’m unfavorable towards this alternative, because almost allpanic!
calls use formatting arguments. Passing anAny
value seems to be the exception.