Pet*_*all 6 error-handling downcast rust
我有以下代码:
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
});
}
Run Code Online (Sandbox Code Playgroud)
当我panic!直接触发 a 时(通过取消注释上面代码中的行),然后我得到一个包含我的错误消息的输出:
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
});
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用Option::expect(&str),如上所述,则消息无法向下转换为&'static str,因此我无法获取错误消息:
Error: Oh no! A horrible error.
Run Code Online (Sandbox Code Playgroud)
我如何获得错误消息,以及在一般情况下如何找到向下转换的正确类型?
Option::expect期望消息为 a &str,即具有任意生命周期的字符串切片。您不能将 a 强制转换&str为 a &\'static str,因为字符串切片可能引用 a 的内部String或Box<str>可以随时释放。如果您要保留 around 的副本&\'static str,则可以在删除Stringor后使用它Box<str>,这将是未定义的行为。
一个重要的细节是该Any特征不能保存任何生命周期信息(因此是\'static界限),因为 Rust 中的生命周期在编译时被删除。编译器使用生命周期来验证程序,但程序无法在运行时区分 a&\'a str和&\'b stra &\'static str。
\n\n\n[...]\xc2\xa0在一般情况下我如何找到正确的类型来向下转换?
\n
不幸的是,这并不容易。Any有一个名为 的方法(从 Rust 1.15.1 开始不稳定)get_type_id,可以让您获取TypeId所引用的具体对象的Any。这仍然没有明确告诉您它是什么类型,因为您仍然必须弄清楚它TypeId属于哪种类型。您必须获得TypeId多种类型的TypeId::of,并查看它是否与您从 获得的类型匹配Any,但您可以使用 执行相同的操作downcast_ref。
在本例中,事实证明Any是一个String. 也许Option::expect最终会被专门化,如果它的生命周期是,它会因字符串切片而恐慌,并且只有在不是时才\'static分配 aString\'static。