Function trait_self_sized_bound

Source
pub fn trait_self_sized_bound()
Expand description

§对象安全规则里,为什么需要 Self: Sized

思考:什么情况下需要 Self: Sized


trait WithConstructor {
    fn build(param: usize) -> Self where Self: Sized;

    fn new() -> Self where Self: Sized {
        Self::build(0)
    }


    fn t(&self){
        println!("T");
    }

    fn p(&self){
        self.t();
        println!("hello");
    }
}

struct A;

impl WithConstructor for A {
    fn build(param: usize) -> Self{
        A
    }

}

fn main(){
    let a : &WithConstructor = &A ;
}

示例 2:


trait Test {
    fn foo(self);

    fn works(self: Box<Self>){
        println!("hello Trait");
    }

    fn fails(self: Box<Self>)
    where Self: Sized
    {
        self.foo()
    }
}

struct Concrete;

impl Concrete {
    fn hello(&self){
        println!("hello");
    }
}

struct Bar;

impl Bar {
    fn hello(&self){
        println!("hello Bar");
    }
}

impl Test for Bar {
    fn foo(self) { () }
    fn works(self: Box<Self>) { self.hello()}
}

impl Test for Concrete {
    fn foo(self) { () }
    fn works(self: Box<Self>) { self.hello()}
}

fn main() {
    let concrete: Box<dyn Test> = Box::new(Concrete);
    concrete.works();
    let concrete: Box<dyn Test> = Box::new(Bar);
    concrete.works();
    // concrete.fails(); // compilation error
}

结论:

  1. Self: Sized 为了保证 trait 默认实现内部的 Self 调用都是合法的。
  2. 防止 函数体内包含了 Self 的默认实现混入虚表。因为虚表内 Self 无法确定。

§Sized vs ?Sized

trait WithConstructor {
    fn build(param: usize) -> Self where Self: ?Sized;

    fn new() -> Self where Self: ?Sized {
        Self::build(0)
    }
}