我想知道以下代码是否有效(也许有一种内置/安全的方法可以将
Rc<dyn SomeTrait>
向下转换为 Rc<SomeType>
?我找不到任何方法),最重要的是,它安全吗?
use std::any::*;
use std::rc::*;
// NOTE: apparently adding Any here is REQUIRED
// otherwise it doesn't work at all,
// I have no idea why
trait SomeTrait: Any {}
struct SomeType;
impl SomeTrait for SomeType {}
fn rc_downcaster<A: 'static, B: ?Sized + 'static>(b: Rc<B>) -> Option<Rc<A>> {
if Any::type_id(&*b) == TypeId::of::<A>() {
Some(unsafe {
let p = Rc::into_raw(b);
Rc::from_raw(p as *const A)
})
} else {
None
}
}
fn main() {
let x: Rc<dyn SomeTrait> = Rc::new(SomeType);
let _: Rc<SomeType> = rc_downcaster(x).unwrap();
}
在不使用 nightly 的情况下,我找到了这个安全的替代解决方案:
use std::any::*;
use std::rc::*;
trait SomeTrait: AsAny {}
struct SomeType;
impl SomeTrait for SomeType {}
trait AsAny {
fn as_any(self: Rc<Self>) -> Rc<dyn Any>;
}
impl<T: 'static> AsAny for T {
fn as_any(self: Rc<Self>) -> Rc<dyn Any> where Self: Sized
{
self
}
}
fn main() {
let x: Rc<SomeType> = Rc::new(SomeType);
let x: Rc<dyn Any> = x.as_any();
let _: Rc<SomeType> = Rc::downcast(x).unwrap();
}
但值得一提@cafce25的解决方案(在评论中):
如果您在 nightly 上,则可以使用 Rc::downcast 并添加 #![feature(trait_upcasting)]。既然这样,你的代码也应该是健全的。 游乐场