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.