Error handling 为什么可以';t Option.expect()消息将被向下转换为&';静态str当恐慌通过catch_unwind处理时?
我有以下代码:Error handling 为什么可以';t Option.expect()消息将被向下转换为&';静态str当恐慌通过catch_unwind处理时?,error-handling,rust,downcast,Error Handling,Rust,Downcast,我有以下代码: use std::thread; use std::panic; pub fn main(){ thread::spawn(move || { panic::catch_unwind(|| { // panic!("Oh no! A horrible error."); let s: Option<u32> = None; s.expect("Nothing was th
use std::thread;
use std::panic;
pub fn main(){
thread::spawn(move || {
panic::catch_unwind(|| {
// panic!("Oh no! A horrible error.");
let s: Option<u32> = None;
s.expect("Nothing was there!");
})
})
.join()
.and_then(|result| {
match result {
Ok(ref val) => {
println!("No problems. Result was: {:?}", val);
}
Err(ref err) => {
if let Some(err) = err.downcast_ref::<&'static str>() {
println!("Error: {}", err);
} else {
println!("Unknown error type: {:?}", err);
}
}
}
result
});
}
但是,如果我使用如上所述的选项::expect(&str)
,则消息不能向下转换到&'static str
,因此我无法获取错误消息:
未知错误类型:任意
如何获取错误消息,以及在一般情况下如何找到要向下转换到的正确类型?期望消息为&str
,即具有任何生存期的字符串片段。您不能将&str
强制为&str的静态str
,因为字符串片段可能指可以随时释放的字符串或框的内部。如果要保留&'static str
的副本,则可以在删除字符串
或框
后使用它,这将是未定义的行为
一个重要的细节是,Any
特性不能保存任何生存期信息(因此,静态
绑定),因为Rust中的生存期在编译时被擦除。编译器使用生存期来验证程序,但程序在运行时无法区分&'a str
和&'b str
与&'static str
[…]在一般情况下,我如何找到要向下转换的正确类型
不幸的是,这并不容易Any
有一个名为的方法(从Rust 1.15.1开始不稳定),该方法允许您获得Any
所指混凝土对象的形状。这仍然不能明确地告诉你那是什么类型,因为你仍然需要弄清楚这个TypeId
属于哪种类型。您必须获得许多类型的TypeId
(使用),并查看它是否与从Any
中获得的匹配,但您可以使用downcast\u ref
执行相同的操作
在本例中,Any
是一个字符串。也许选项::expect
最终会被专门化,这样,如果字符串片的生存期是静态的,它就会对字符串片产生恐慌,如果字符串片不是静态的,它只分配字符串
,,就像弗朗西斯说的,一般来说,你不能发现并转换为恐慌的类型。然而,尽管如此,恐慌有以下规则:
- 如果你惊慌失措代码>使用单个参数,恐慌将具有该类型。通常这是
&'static str
- 如果你惊慌失措
如果有多个参数,这些参数将被视为格式代码>参数,用于创建字符串
参数
这些规则记录在panic
文档中:
考虑到这些规则,我们可以编写一个函数,在任何情况下从恐慌中提取消息,其中有一条消息可提取,这在实践中大部分时间都有效,因为大部分时间消息要么是&'static str
要么String
:
pub fn获取恐慌消息(恐慌:&Box)->选项{
恐慌
//尝试将其转换为字符串,然后将其转换为str
.downcast_ref::()
.map(字符串::as_str)
//如果失败,尝试将其转换为&'static str
。或| else(| | panic.downcast_ref::谢谢。我做了一些测试,发现即使是panic!(my|str)
在运行时构建my|str
时,也会被捕获为字符串。因此panic!()
的行为实际上正是您所描述的“也许最终”选项的行为::expect
。