Rust: doesn't have a size known at compile-time

use std::fmt::Debug;

#[derive(Debug)]
struct Node<K: Debug,V: Debug> {
    key: K,
    value: V,
}

fn myprint<K:Debug+?Sized, V:Debug+?Sized>(node: &Node<K, V>) {
    println!("{:?}", node);
}

fn main() {
    let node = Node{key: "xxx", value: "yyy"};
    myprint(&node);
}

Complie error:
error[E0277]: the size for values of type K cannot be known at compilation time
--> src/main.rs:23:50
|
18 | struct Node<K: Debug,V: Debug> {
| - required by this bound in Node
...
23 | fn myprint<K:Debug+?Sized, V:Debug+?Sized>(node: &Node<K, V>) {
| - ^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| this type parameter needs to be std::marker::Sized

But following code works ok:

use std::fmt::Debug;

fn myprint<K:Debug+?Sized, V:Debug+?Sized>(k: &K, v: &V) {
    println!("{:?}, {:?}", k, v);
}

fn main() {
    myprint("aaa", "bbb");
}

For reference, so that answerers won't accidentally duplicate info:


As for the question itself - you can't relax requirements already specified on the type. Node<K, V> requires both parameters to be Sized, so you can't use it with type which are ?Sized. Debug, on the other hand, doesn't have any restrictions.

1 Like

For structs, only the last field can be a dynamically sized type. Otherwise, it is not possible to calculate the offset to the fields succeeding a dynamically sized field.

You can work around this limitation by storing separate references in the struct, similar to what you do in the second version:

use std::fmt::Debug;

#[derive(Debug)]
struct Node<'a, K: Debug + ?Sized, V: Debug + ?Sized> {
    key: &'a K,
    value: &'a V,
}

fn myprint<K: Debug + ?Sized, V: Debug + ?Sized>(node: &Node<K, V>) {
    println!("{:?}", node);
}

Alternatively, you can use Box.

1 Like