Why does returning `Self` in trait work, but returning `Option` requires `Sized`?

There are two sets of checks happening here, which is why the difference appears confusing.

  1. Each type in the function signature is checked for validity. Option inherently requires T: Sized. A return type that doesn’t require Sized is fine:

    trait Works {
        fn foo() -> Box<Self>;
    }
    

    The existing answer covers this well.

  2. Any function with a body also checks that all of the parameters are Sized. Trait functions without a body do not have this check applied.

    Why is this useful? Allowing unsized types to be used in trait methods is a key part of allowing by-value trait objects, a very useful feature. For example, FnOnce does not require that Self be Sized:

    pub trait FnOnce<Args> {
        type Output;
        extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    }
    
    fn call_it(f: Box<dyn FnOnce() -> i32>) -> i32 {
        f()
    }
    
    fn main() {
        println!("{}", call_it(Box::new(|| 42)));
    }
    

A big thanks to pnkfelix and nikomatsakis for answering my questions on this topic.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)