我有以下代码:
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
});
}
当我引发恐慌!直接(通过取消注释上面代码中的行),然后我得到一个包含我的错误消息的输出:
Error: Oh no! A horrible error.
但是,如果我使用Option :: expect(& str),如上所述,那么消息不能向下转换为&’static str,所以我无法得到错误消息:
Unknown error type: Any
如何获取错误消息,如何在一般情况下找到正确的向下转换类型?
最佳答案
Option::expect
期望消息为& str,即具有任何生命周期的字符串切片.你不能将& str强制转换为&’静态str,因为字符串切片可以引用String或Box< str>的内部.可以在任何时候释放.如果你要保留&’静态str的副本,你就可以在String或Box< str>之后使用它.已被删除,这将是未定义的行为.
一个重要的细节是Any trait不能保存任何生命周期信息(因此是’静态绑定),因为Rust的生命周期在编译时被删除.编译器使用生命周期来验证您的程序,但程序无法在运行时将&’str和&’b str与&’静态str区分开来.
[…] how would I find the correct type to downcast to in the general case?
不幸的是,这并不容易.任何一个名为get_type_id
的方法(不稳定的Rust 1.15.1)都可以让你获得Any引用的具体对象的TypeId
.这仍然没有明确告诉你什么类型,因为你仍然需要弄清楚这个TypeId属于哪种类型.你必须获得许多类型的TypeId(使用TypeId::of
)并查看它是否与你从Any获得的类型匹配,但你可以使用downcast_ref.
在这个例子中,事实证明Any是一个字符串.也许Option :: expect最终可能是专用的,如果它的生命周期是’静态的话它会对字符串切片感到恐慌,如果它不是’静态的话只分配一个字符串.