1

I have the following trait definition representing a sub-block within a DSL:

pub trait SubBlock {
    fn get_command(&self) -> Command;
    fn get_parent_id(&self) -> u32;
}

I also have the following struct/enum definitions:

pub struct StartBlock {
    pub parent_id: u32,
    pub date: NaiveDate,
    pub hour: u32,
}

impl SubBlock for StartBlock {
    fn get_command(&self) -> Command {
        Command::START
    }

    fn get_parent_id(&self) -> u32 {
        self.parent_id
    }
}

pub struct Entry {
    pub id: u32,
    pub description: String,
    pub children: Option<Vec<Box<dyn SubBlock>>>
}

So, as can be seen, some Entrys have children, which are all SubBlocks, but there are a series of struct definitions specific to the DSL for these SubBlocks. For example, a StartBlock has a date and hour.

The problem is that I want to be able to clone an Entry struct, so I wrote this method:

impl Clone for Entry {
    fn clone(&self) -> Self {
        let cloned_children: Vec<Box<dyn SubBlock>> = self.children.unwrap()
            .iter()
            .map(|bsb| {
              *bsb
            })
            .collect();
        let mut opt_cloned_children = None;
        if cloned_children.len() > 0 {}
        opt_cloned_children = Some(cloned_children);

        Entry {
            id: self.id,
            description: String::from(&self.description),
            children: opt_cloned_children
        }
    }

But, when I try to compile this code, I get:

error[E0277]: the size for values of type `dyn SubBlock` cannot be known at compilation time
  --> src/entry.rs:22:18
   |
22 |               .map(|bsb| {
   |  ______________---_^
   | |              |
   | |              required by a bound introduced by this call
23 | |                 *bsb
24 | |             })
   | |_____________^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn SubBlock`

Clearly, I know this isn't quite right, since I'm dereferencing the box, which is a pointer (and thus unsized), but all I really want to do is put a copy of the data into a new Box. I even tried doing something akin to:

            .map(|bsb| {
                Box::new(StartBlock::try_from(bsb).unwrap())
            })


(After implementing try_from for a StartBlock, which uses the mopa crate to downref:

pub trait SubBlock: mopa::Any {
    fn get_command(&self) -> Command;
    fn get_parent_id(&self) -> u32;
}

mopafy!(SubBlock);

impl TryFrom<Box<dyn SubBlock>> for StartBlock {
    type Error = ConversionError;

    fn try_from(value: Box<dyn SubBlock>) -> Result<Self, Self::Error> {
        if value.get_command() != Command::START {
            return Err(ConversionError {
                initial_type: Command::START
            });
        }

        let converted_opt: Option<&StartBlock> = value.downcast_ref::<StartBlock>();

        if converted_opt.is_none() {
            return Err(ConversionError {
                initial_type: Command::START
            });
        }

        let dc_ref = converted_opt.unwrap();
        Ok(StartBlock {
            parent_id: dc_ref.parent_id,
            date: dc_ref.date.clone(),
            hour: dc_ref.hour
        })
    }
}

But, then this results in:

error[E0277]: a value of type `Vec<Box<dyn PlaSubBlock>>` cannot be built from an iterator over elements of type `Box<sub_blocks::PlaStartBlock>`
  --> src/entry.rs:25:14
   |
25 |             .collect();
   |              ^^^^^^^ value of type `Vec<Box<dyn SubBlock>>` cannot be built from `std::iter::Iterator<Item=Box<sub_blocks::StartBlock>>`
   |
   = help: the trait `FromIterator<Box<sub_blocks::StartBlock>>` is not implemented for `Vec<Box<dyn SubBlock>>`

Can I directly implement FromIterator<Box<StartBlock>> on Vec<Box<dyn SubBlock>>? That doesn't seem likely. I'm having a difficult time understanding how I can clone something when I don't have a concrete type (or if that is even possible).

Herohtar
  • 5,347
  • 4
  • 31
  • 41
jwir3
  • 6,019
  • 5
  • 47
  • 92
  • [The duplicate's answer applied to your case](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c1af3024e4dab698637f893c57d614f9) – trent Feb 07 '22 at 07:26

0 Answers0