This only needs `&dyn Any`, but we keep a `Box` all the way to avoid the risk of a subtle bug in the caller where `&Box ` is coerced to `&dyn Any` by unsizing with another layer of vtable and wide pointer, instead of the expected auto-deref.
(_py: Python, panic: Box<dyn any::Any>)
| 243 | // `&dyn Any` by unsizing with another layer of vtable and wide pointer, |
| 244 | // instead of the expected auto-deref. |
| 245 | fn handle_panic(_py: Python, panic: Box<dyn any::Any>) { |
| 246 | let panic_str = if let Some(s) = panic.downcast_ref::<String>() { |
| 247 | Some(s.as_str()) |
| 248 | } else if let Some(s) = panic.downcast_ref::<&'static str>() { |
| 249 | Some(*s) |
| 250 | } else { |
| 251 | None |
| 252 | }; |
| 253 | let panic_cstring = panic_str.and_then(|s| { |
| 254 | let result = CString::new(format!("Rust panic: {}", s)); |
| 255 | // Give up on representing the panic payload if it contains a null byte |
| 256 | // TODO: use PyErr_SetObject instead, so a `char*` string isn’t needed? |
| 257 | result.ok() |
| 258 | }); |
| 259 | let msg = if let Some(s) = &panic_cstring { |
| 260 | s.as_c_str() |
| 261 | } else { |
| 262 | cstr!("Rust panic") |
| 263 | }; |
| 264 | unsafe { |
| 265 | ffi::PyErr_SetString(ffi::PyExc_SystemError, msg.as_ptr()); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | pub struct AbortOnDrop<'a>(pub &'a str); |
| 270 |
no test coverage detected