This trait definition compiles fine:
trait Works { fn foo() -> Self; } This, however, does lead to an error:
trait Errors { fn foo() -> Option<Self>; } error[E0277]: the size for values of type `Self` cannot be known at compilation time --> src/lib.rs:6:5 | 6 | fn foo() -> Option<Self>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> = help: consider adding a `where Self: std::marker::Sized` bound = note: required by `std::option::Option` With the : Sized supertrait bound, it works.
I know that the Self type in traits is not automatically bound to be Sized. And I understand that Option<Self> cannot be returned (via the stack) unless it is sized (which, in turn, requires Self to be sized). However, the same would go for Self as return type, right? It also cannot be stored on the stack unless it's sized.
Why doesn't the first trait definition already trigger that error?
(This question is related, but it doesn't answer my exact question – unless I didn't understand it.)