Isn't this type sized?


#1

I have a tree structure of nodes, where I want each node to be able to send and receive messages to/from other nodes. I have an issue with storing the children of each node, though:

pub trait Node
{
    type MessageType;
}

pub struct NodeWrapper<MessageType>
{
    id          : NodeId,
    name        : Option<String>,
    children    : Vec<NodeWrapper<Any>>,
    node        : Box<Node<MessageType=MessageType>>,
}

This complains that NodeWrapper<Any> isn’t Sized, which it needs to be store in a Vec I guess. However, logically, the generic parameter doesn’t make this not-sized, as it just represents the associated type. The trait object’s size is known at compile-time. Is this a limitation of the type-system, can I work around this, or am I just being dim?

Thanks


#2

You are correct, NodeWrapper<Any> is sized. But the error message I see does not say that NodeWrapper<Any> is unsized, it says that Any is unsized; which indeed is true.

   Compiling playground v0.0.1 (file:///playground)
error[E0277]: the trait bound `std::any::Any + 'static: std::marker::Sized` is not satisfied
  --> src/main.rs:13:5
   |
13 |     children    : Vec<NodeWrapper<Any>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `std::any::Any + 'static` does not have a constant size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `std::any::Any + 'static`
note: required by `NodeWrapper`
  --> src/main.rs:9:1
   |
9  | pub struct NodeWrapper<MessageType>
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The error message notably points to two things:

  • the children field
  • the definition of NodeWrapper

And yes, these two things do conflict. Generic type parameters always come with an implicit Sized bound, meaning that your definition of NodeWrapper is equivalent to:

pub struct NodeWrapper<MessageType: Sized>
{ ... }

which would make MessageType<Any> invalid.

To resolve the error, you can disable this sized requirement with the syntax ?Sized:

pub struct NodeWrapper<MessageType: ?Sized>
{ ... }

Playground link to code that compiles


#3

Ah, I’d even almost stumbled across that solution myself :man_facepalming:. Thank you very much