我想知道下面的代码是否有效(也许有一种内置/安全的方法将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();
}

Playground

推荐答案

在没有使用夜间服务的情况下,我找到了一个安全的替代解决方案:

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<dyn SomeTrait> = Rc::new(SomeType);
    let x: Rc<dyn Any> = x.as_any();
    let _: Rc<SomeType> = Rc::downcast(x).unwrap();
}

但值得一提的是@afce25的解决方案(在 comments 中):

如果您是夜间开机,可以使用rc::Downcast并添加#![FEATURE(TRIGNAL_UPCAST)].既然这是可行的,那么您的代码也应该是健全的.Playground

Rust相关问答推荐

有条件默认实现

什么是谓词的简短和简洁类型

交叉术语未正确清除屏幕

带扫描的铁 rust 使用滤镜

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

在Rust中声明和定义一个 struct 体有什么区别

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

对于rustc编译的RISC-V32IM二进制文件,llvm objdump没有输出

为什么在 Allocator API 中 allocate() 使用 `[u8]` 而 deallocate 使用 `u8` ?

结果流到 Vec 的结果:如何避免多个into_iter和collect?

Rust 中的生命周期:borrow 的 mut 数据

打印 `format_args!` 时borrow 时临时值丢失

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

Rust 中的let是做什么的?

为什么 Rust 编译器在移动不可变值时执行复制?

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

BigUint 二进制补码

Rust 为什么 (u32, u32) 的枚举变体的大小小于 (u64)?

Rust 中的运行时插件

为什么在使用 self 时会消耗 struct 而在解构时不会?