Remove <dyn Trait> from const struct

For example, I create some structs that have a field implementing a Trait. I don't want to propagate the dyn whenever I use this Trait. Any way of removing this?

I want something like pub fn new() -> Y<'a, What> instead.

My first question would be, why do you need to remove the dyn if you are looking to use it in a const context?

Also, since you are referencing a const value, you can just use a 'static lifetime.

This probably destroys whatever functionality you're after, but does technically remove the dyn: playground link

1 Like

Example of the failure:

pub trait What {}

impl What for u8 {}

pub struct Y<'a, W: What + ?Sized> {
   a: &'a W
}

impl<'a, W: What> Y<'a, W> {
    pub fn new() -> Y<'a, dyn What> {
        YIKES
    }
}

pub const YIKES: Y<dyn What> = Y {
    a: &5
};

pub struct Other<'a, W: What> {
    y: Y<'a, W>,
}

impl<'a, W: What> Other<'a, W> {
    pub fn new() -> Self {
        Self {
            y: YIKES
        }
    }
}
   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/lib.rs:26:16

   |
23 | impl<'a, W: What> Other<'a, W> {
   |          - this type parameter
...
26 |             y: YIKES
   |                ^^^^^ expected `Y<'_, W>`, found `Y<'_, dyn What>`
   |
   = note: expected struct `Y<'a, W>`
              found struct `Y<'static, (dyn What + 'static)>`
   = help: type parameters must be constrained to match other types
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

Interesting, this may work. I want an external user to provide the What trait. So I think it could be just a const.

what do you mean? What is a trait, and a trait is not a type (unlike java or C#), so, Y<'a, What> is not valid type in rust; on the other hand, dyn What IS a (unsized) type, so the original code is valid.

if you mean Y<'a, W>, then it is not not possible, because the trait bounds W: What provide no means to construct a reference to type W, which means you have no way to construct a value of the return type (which need a reference to the generic argument W).

1 Like

As I see the issue - to make the const versions you must specify a concrete type. So, when you go to use them, the potential for generic types is already closed off. Thus a function that returns your YIKES already has a single concrete type.

That being said, this might be closer to useful: playground

Here's a bit more deconstructed version that decouples the type selection, perhaps giving what you're after: playground

Thanks. I'm probably still missing some fundamental understanding that's causing this error:

When you have something like this:

fn example<W: What>(a: u8) -> Container<W> { todo!() }

The caller chooses W, so you can't return a Container<u8> -- the caller may have needed a Container<u32> or some other implementor of What.

And the same is true here; you're saying you're implementing the function for all Container<W> where W: What. Self is an alias for Container<W>, and the caller gets to choose the W (so long as the bounds are met). You have to return a Container<W>, not a Container<u8>.

impl<W: What> Container<W> {
    fn another_one(a: u8) -> Self { todo!() }
}

If we keep going, there's going to be other challenges, like you can't return references to local variables, as those references would immediately dangle.

Also, if I look at these together:

pub trait What {}
impl What for u8 {}
impl What for f32 {}

pub struct Container<W: What + 'static> {
    one: u8,
    two: u32,
    y: &'static W,
}

I get the feeling you're trying to create a self-referencial struct (where c.y points to one of c.one or c.two). This won't work for a couple reasons:

  • W has to resolve to a single type, while one and two have different types
  • You can't create self-referencial structs in safe Rust without making them almost unusable

For example you can't move a self-referencial struct, as the reference would dangle.

1 Like

Thanks for all the help with increasing my understanding, I eventually figured out a solution: WIP: Initial Custom Compression algorithm support by wcampbell0x2a · Pull Request #228 · wcampbell0x2a/backhand · GitHub. Or at least a solution, lmk if I messed something up.

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.