I defined a trait Foo, implemented this trait for [u32], and wrote a function bar taking this trait as argument (playground):
trait Foo {
fn foo(&self) -> u32;
}
impl Foo for [u32] {
fn foo(&self) -> u32 {
self[0]
}
}
fn bar<T>(f: &T) -> u32
where
T: Foo,
{
f.foo() + 1
}
fn main() {
let f: &[u32] = &[42];
bar(f);
}
This does not compile because bar implicitly expects its arguments to be Sized:
error[E0277]: the trait bound `[u32]: std::marker::Sized` is not satisfied
--> src/main.rs:20:5
|
20 | bar(f);
| ^^^ `[u32]` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
note: required by `bar`
--> src/main.rs:11:1
|
11 | / fn bar<T>(f: &T) -> u32
12 | | where
13 | | T: Foo,
14 | | {
15 | | f.foo() + 1
16 | | }
| |_^
I can fix it with T: Foo + ?Sized, but then I would have to do this for every function expecting a Foo, which is a pain...
Can I declare once and for all that implementations of Foo should not be expected to be Sized? I tried trait Foo: ?Sized in line 1, but the compiler complains about it.
This question is not the same as Trait implementing Sized. In that question, the Foo parameter is moved, so it is normal that the compiler wants to know its size at compile time. In my case, the parameter is a reference, so it does not need to be sized -- but still the compiler implicitly assumes it is, unless explicitly told (using + ?Sized). What I would like to change is this implicit assumption, for this particular trait.