Can't return slice of boxed traits

This does not compile.

pub trait Foo {}

pub trait Bar: Foo {}

pub trait HasFoos<T: Foo> {
    fn foos(&self) -> &[Box<T>];
}

pub struct HasBars {
    bars: Vec<Box<Bar>>
}

impl HasBars {
    pub fn new(bars: Vec<Box<Bar>>) -> Self {
        HasBars {
            bars
        }
    }

    fn bars(&self) -> &[Box<Bar>] {
        &self.bars
    }
}

impl HasFoos<Bar> for HasBars {
    fn foos(&self) -> &[Box<Bar>] {
        &self.bars
    }
}
error[E0277]: the size for values of type `(dyn physics::spike::Bar + 'static)` cannot be known at compilation time
  --> evo_model\src\physics\spike.rs:25:6
     |
25 | impl HasFoos<Bar> for HasBars {
     |         ^^^^^^^^^^^^ doesn't have a size known at compile-time

But I don’t understand why not. Why does it need to know the size of Bars? They’re all in boxes.

Sized is a default, can override using

pub trait HasFoos<T: Foo + ?Sized> {
1 Like

Generic parameter have a default constraint T: Sized, to remove that constraint use T: ?Sized

Thank you both. That works. But that leads to a new problem:

pub struct HasHasFoos<H, F>
    where H: HasFoos<F>, F: Foo + ?Sized
{
    has_foos: H
}
error[E0392]: parameter `F` is never used
  --> evo_model\src\physics\spike.rs:31:26
   |
31 | pub struct HasHasFoos<H, F>
   |                          ^ unused type parameter
   |
   = help: consider removing `F` or using a marker such as `std::marker::PhantomData`

Hmm, maybe I want to be using an associated type instead. Investigating…

Okay, I got it to work using an associated type. Here it is for posterity:

pub trait Foo {}

pub trait Bar: Foo {}

pub trait HasFoos {
    type F: Foo + ?Sized;

    fn foos(&self) -> &[Box<Self::F>];
}

pub struct HasBars {
    bars: Vec<Box<Bar>>
}

impl HasBars {
    pub fn new(bars: Vec<Box<Bar>>) -> Self {
        HasBars {
            bars
        }
    }

    fn bars(&self) -> &[Box<Bar>] {
        &self.bars
    }
}

impl HasFoos for HasBars {
    type F = Bar;

    fn foos(&self) -> &[Box<Self::F>] {
        &self.bars
    }
}

pub struct HasHasFoos<H>
    where H: HasFoos
{
    has_foos: H
}