diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2020-10-24 22:39:53 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-24 22:39:53 +0200 |
| commit | e3808edeeea28c137129c0c5bf70c24562e794f5 (patch) | |
| tree | c58e4147d059534a0c5151944ff6da1ff3e9b8f6 | |
| parent | e12e97223f9f0bb0f2806334029aec1d9790f074 (diff) | |
| parent | 9890217c0eedcbe4742e412ea59e851ecd500bf5 (diff) | |
| download | rust-e3808edeeea28c137129c0c5bf70c24562e794f5.tar.gz rust-e3808edeeea28c137129c0c5bf70c24562e794f5.zip | |
Rollup merge of #78119 - fusion-engineering-forks:panic-use-as-str, r=Amanieu
Throw core::panic!("message") as &str instead of String.
This makes `core::panic!("message")` consistent with `std::panic!("message")`, which throws a `&str` and not a `String`.
This also makes any other panics from `core::panicking::panic` result in a `&str` rather than a `String`, which includes compiler-generated panics such as the panics generated for `mem::zeroed()`.
---
Demonstration:
```rust
use std::panic;
use std::any::Any;
fn main() {
panic::set_hook(Box::new(|panic_info| check(panic_info.payload())));
check(&*panic::catch_unwind(|| core::panic!("core")).unwrap_err());
check(&*panic::catch_unwind(|| std::panic!("std")).unwrap_err());
}
fn check(msg: &(dyn Any + Send)) {
if let Some(s) = msg.downcast_ref::<String>() {
println!("Got a String: {:?}", s);
} else if let Some(s) = msg.downcast_ref::<&str>() {
println!("Got a &str: {:?}", s);
}
}
```
Before:
```
Got a String: "core"
Got a String: "core"
Got a &str: "std"
Got a &str: "std"
```
After:
```
Got a &str: "core"
Got a &str: "core"
Got a &str: "std"
Got a &str: "std"
```
| -rw-r--r-- | library/std/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/std/src/panicking.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/panic-uninitialized-zeroed.rs | 4 |
3 files changed, 20 insertions, 3 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 30e7a7f3c3b..3da0ebdd498 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -259,6 +259,7 @@ #![feature(exhaustive_patterns)] #![feature(extend_one)] #![feature(external_doc)] +#![feature(fmt_as_str)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 8dceb12de87..221ae809e23 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -478,10 +478,26 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { } } + struct StrPanicPayload(&'static str); + + unsafe impl BoxMeUp for StrPanicPayload { + fn take_box(&mut self) -> *mut (dyn Any + Send) { + Box::into_raw(Box::new(self.0)) + } + + fn get(&mut self) -> &(dyn Any + Send) { + &self.0 + } + } + let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + if let Some(msg) = msg.as_str() { + rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc); + } else { + rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc); + } }) } diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 24474cabf1e..4a91198ab9f 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -53,8 +53,8 @@ enum LR_NonZero { fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { let err = panic::catch_unwind(op).err(); assert_eq!( - err.as_ref().and_then(|a| a.downcast_ref::<String>()).map(|s| &**s), - Some(msg) + err.as_ref().and_then(|a| a.downcast_ref::<&str>()), + Some(&msg) ); } |
