Convert `Weak<T>` to `Weak<dyn Trait>` where `T` implements trait `Trait`

How to convert Weak<T> into Weak<dyn Trait> where T: Trait + ?Sized?

I've tried type cast, but it requires T to be Sized

fn convert<T: Trait + ?Sized>(weak: Weak<T>) -> Weak<dyn Trait> {
    weak as _
}
error[E0277]: the size for values of type `T` cannot be known at compilation time
 --> src/lib.rs:6:5
  |
5 | fn convert<T: Trait + ?Sized>(weak: Weak<T>) -> Weak<dyn Trait> {
  |            - this type parameter needs to be `Sized`
6 |     weak as _
  |     ^^^^ doesn't have a size known at compile-time
  |
  = note: required for the cast from `std::sync::Weak<T>` to `std::sync::Weak<dyn Trait>`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
  |
5 - fn convert<T: Trait + ?Sized>(weak: Weak<T>) -> Weak<dyn Trait> {
5 + fn convert<T: Trait>(weak: Weak<T>) -> Weak<dyn Trait> {
  |

Playground link: Rust Playground

In general, it's impossible to get dyn Trait from already dynamically-sized value - any dynamically-sized value needs some metadata to be interpreted, and Rust expects that there will be always only one set of such metadata, not two. What are you trying to do, actually?

1 Like

I'm trying to write an item registry like HashMap<usize, Weak<dyn Item>>. However I could only get weak refs to concrete but dynamic sized types. You are right, theoretically this transformation itself cannot be achieved. Maybe I need to consider modifying other APIs.

I don't know if it applies to your use case, but one of the few places coercing unsized types to dyn Trait is possible is the unstable trait upcasting feature.

You can do manual upcasting on stable, but only with accepted receiver types, and Weak isn't one of those. You could round trip through Arc,[1] which is a supported receiver type.

Or AsTrait like tricks might be helpful in other ways depending on what you control and other details.


  1. or Rc ↩ī¸Ž

If you can add an impl and are okay with an extra redirection, you can put another box around it to make it sized:

use std::sync::Weak;

trait Trait {}
impl<T: ?Sized> Trait for Weak<T> where T: Trait {}

fn convert<'a, T: Trait + ?Sized + 'a>(weak: Weak<T>) -> Box<dyn Trait + 'a> {
    Box::new(weak)
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.