Description
The following code snippet will generate an E0277 error - I've elided some as it's not entirely necessary for the whole context, but this is not runnable:
type SomeType = /* whatever */;
fn do_something(iter: Iterator<SomeType>) {}
fn get_some_iterator() -> Iterator<SomeType> {
...
}
fn main() {
let iterator = get_some_iterator();
do_something(iterator);
}
E0277 indicates the following message:
error: the trait bound `std::iter::Iterator<Item=SomeType> + 'static: std::marker::Sized` is not satisfied [E0277]
help: run `rustc --explain E0277` to see a detailed explanation
note: `std::iter::Iterator<Item=SomeType> + 'static` does not have a constant size known at compile-time
note: all local variables must have a statically known size
I want to stress that yes, this error is factually correct: The reason why I have this error is because the naked trait Iterator
has no defined size at compile time, and that the solution is to either Box
or borrow an Iterator
(and thus rely on dynamic dispatch) or convert do_something
into a generic function so that it is then monomorphised and Rust is aware of the size of the object at compile time.
My suggestion is that the error message is not entirely clear: While it is true that the error is due to the trait size being undefined, coming from another language (like C#/Java/TypeScript) which uses interfaces, this can be confusing as traits are almost-but-not-quite analogous to interfaces. It may be useful to add an extra note to this error message (or accompanying docs) when passing a bare trait with something along the lines of:
note: You appear to be passing a bare trait object as a parameter. ...
And explain in some basic detail the difference between these approaches. For example:
Passing a trait in this manner results in an undefined size at compile time because the implementation of the Trait is unknown until runtime. You should either place the Trait in a
Box
or immutable borrow which will enable the type to be resolved at runtime (and use dynamic dispatch) or alter the function to use the Trait as a generic bound (and be monomorphised and use static dispatch).
Note: This behaviour led me to write this article when trying to fully understand the topic.