rust - Why is `Sized` bound necessary in this trait? -


i have simple trait 2 associated functions this:

trait withconstructor : sized {      fn new_with_param(param: usize) -> self;      fn new() -> self {         self::new_with_param(0)     }  } 

the default implementation of second method (new()) force me put sized bound on type. why ?

(i think it's because of stack pointer manipulation, i'm not sure @ 100%)

edit

if compiler needs know size allocate memory on stack, why in following example doesn't require sized t in simplestruct ?

struct simplestruct<t> {     field: t, }  fn main() {     let s = simplestruct { field: 0u32 }; } 

as know, types in rust can sized , unsized. unsized types, name suggest, not have size required store values of type known compiler. example, [u32] unsized array of u32s; because number of elements not specified anywhere, compiler doesn't know size. example bare trait object type, example, display, when used directly type:

let x: display = ...; 

in case compiler not know type used here, erased, therefore not know size of values of these types. , that's why above line not valid - you can't make local variable without knowing size (to allocate enough bytes on stack), , can't pass value of unsized type function argument or return one.

unsized types can used through pointer, however, can carry additional information - length of available data slices (&[u32]) or pointer virtual table (box<sometrait>). because pointers have fixed , known size, can stored in local variables , passed or returned functions.

given concrete type can whether sized or unsized. generics, however, question arises - type parameter sized or not?

fn generic_fn<t>(x: t) -> t { ... } 

if t unsized, such function definition incorrect, can't pass unsized values around directly. if sized, ok.

and in rust generic type parameters default sized (everywhere - in functions, in structs , in traits), is, have implicit sized bound (where sized trait marking sized types):

fn generic_fn<t: sized>(x: t) -> t { ... } 

this because in overwhelming number of times want generic parameters sized. sometimes, however, you'd want opt-out of sizedness, , can done ?sized bound:

fn generic_fn<t: ?sized>(x: &t) -> u32 { ... } 

here generic_fn can called generic_fn("abcde"), , t instantiated str unsized, that's ok - function accepts reference t, nothing bad happens.

however, there place question of sizedness important. traits in rust implemented type:

trait {     fn do_something(&self); }  struct x; impl x {     fn do_something(&self) {} } 

however, necessary convenience , practicality purposes. possible define traits take 1 type parameter , not specify type trait implemented for:

// not actual rust rust-like language  trait a<t> {     fn do_something(t: &t); }  struct x; impl a<x> {     fn do_something(t: &x) {} } 

that's how haskell type classes work, and, in fact, that's how traits implemented in rust on lower level.

each trait in rust has implicit type parameter, called self, designates type trait implemented for. available in body of trait:

trait {     fn do_something(t: &self); } 

and question of sizedness comes picture. self parameter sized?

it turns out no, self not sized default in rust. each trait has implicit ?sized bound on self. 1 of reasons needed because there lot of traits can implemented unsized types , still work. example, trait contains methods take , return self reference, can implemented unsized types. can read more motivation in this rfc.

sizedness not issue when define signature of trait , methods. because there no actual code in these definitions, compiler can't assume anything. however, when start writing generic code uses trait, includes default methods because take implicit self parameter, should take sizedness account. because self not sized default, default trait methods can't return self value or take parameter value. consequently, either need specify self must sized default:

trait a: sized { ... } 

or can specify method can called if self sized:

trait withconstructor {     fn new_with_param(param: usize) -> self;      fn new() -> self self: sized {         self::new_with_param(0)     } } 

Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -