Upcasting an `Arc` to an `Arc`?

huangapple go评论64阅读模式
英文:

Upcasting an `Arc<dyn Trait>` to an `Arc<dyn Any>`?

问题

假设我有一个类型为 `Asset` 的特性对象,它存储在一个 `Arc` 中,并且我想将它转换为一个 `Arc&lt;dyn Any&gt;` 以便之后进行下转型。

有没有安全的方法可以做到这一点?我尝试了使用 [`as-any`](https://docs.rs/as-any/latest/as_any/) crate 的这种(不安全的)策略,但似乎它会破坏类型信息,因为我无法将得到的 `Arc&lt;dyn Any&gt;` 转换回它的基本类型:

        let res: Box&lt;dyn Asset&gt; = thing_that_returns_dyn_asset();
        let res: Arc&lt;dyn Asset&gt; = Arc::from(res);

        // 不安全:将 Arc&lt;dyn Asset&gt; 转换为 Arc&lt;dyn Any&gt;。
        let res : Arc&lt;dyn Any&gt; = unsafe {
             Arc::from_raw(Arc::into_raw(res).as_any())
        };

但似乎并不起作用。我知道目前有一个实验性的功能可以向上转型对象,但那似乎并没有帮助。
英文:

Suppose I have a trait object of type Asset, which is stored in an Arc, and I want to convert it to an Arc&lt;dyn Any&gt; to facilitate later downcasting.

Is there any safe way to do this? I have tried this (unsafe) strategy using the as-any crate, but it seems to break the type information as I can't downcast the resulting Arc&lt;dyn Any&gt; to its base type:

    let res: Box&lt;dyn Asset&gt; = thing_that_returns_dyn_asset();
    let res: Arc&lt;dyn Asset&gt; = Arc::from(res);

    // Unsafe: Cast an Arc&lt;dyn Asset&gt; to an Arc&lt;dyn Any&gt;.
    let res : Arc&lt;dyn Any&gt; = unsafe {
         Arc::from_raw(Arc::into_raw(res).as_any())
    };

But it does not seem to work. I'm aware that there's a currently experimental feature to upcast objects, but that doesn't seem to help.

答案1

得分: 1

The easiest way is to add a method that casts from Arc<Asset> to Arc<dyn Any>. Following as-any, we can do that in a custom trait and have a blanket implementation for it:

pub trait AsAnyArc {
    fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any>;
}

impl<T: 'static> AsAnyArc for T {
    fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> { self }
}

pub trait Asset: AsAnyArc { ... }

let res: Box<dyn Asset> = thing_that_returns_dyn_asset();
let res: Arc<dyn Asset> = Arc::from(res);

let res: Arc<dyn Any> = res.as_any_arc();
英文:

The easiest way is to add a method that casts from Arc&lt;Asset&gt; to Arc&lt;dyn Any&gt;. Following as-any, we can do that in a custom trait and have a blanket implementation for it:

pub trait AsAnyArc {
    fn as_any_arc(self: Arc&lt;Self&gt;) -&gt; Arc&lt;dyn Any&gt;;
}

impl&lt;T: &#39;static&gt; AsAnyArc for T {
    fn as_any_arc(self: Arc&lt;Self&gt;) -&gt; Arc&lt;dyn Any&gt; { self }
}

pub trait Asset: AsAnyArc { ... }

let res: Box&lt;dyn Asset&gt; = thing_that_returns_dyn_asset();
let res: Arc&lt;dyn Asset&gt; = Arc::from(res);

let res: Arc&lt;dyn Any&gt; = res.as_any_arc();

huangapple
  • 本文由 发表于 2023年5月11日 05:43:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76222743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定