compiler errors - Spurious requirement for std::marker::Sized -


update: simpler code (play) exhibits same symptoms:

use std::fmt::display;  pub fn arg(a: &str, b: &display) { }  fn main() {     arg("foo", "bar"); } 

gives error:

<anon>:7:16: 7:21 error: trait `core::marker::sized` not implemented type `str` [e0277] <anon>:7     arg("foo", "bar");                         ^~~~~ <anon>:7:16: 7:21 note: `str` not have constant size known @ compile-time <anon>:7     arg("foo", "bar");                         ^~~~~ 

but don't see reason require size here. a , b treated same, same type, , there no problem a. so

  • why have problem b, and
  • how tell trait not expected have size known.

in fact, it's trait type, never has type known no matter underlying type is. why want size?

oh, , should not forget: in actual use-case need dynamic polymorphism. function (method) chained arguments of different actual types , references stored (see original exhibit below), can't convert t: trait + ?sized.


original exhibit:

i have code following (see on play.rust-lang.org):

pub trait trait { /* methods */ }  impl trait str { /* implementation */ }  pub struct struct<'a> {     args: hashmap<&'a str, &'a trait>, }  impl<'a> struct<'a> {     pub fn new() -> self {         struct { args: hashmap::new() }     }      pub fn arg(mut self, key: &'a str, value: &'a trait) -> struct<'a> {         self.args.insert(key, value);         return self;     }      // of course there process collected arguments }  fn main() {     struct::new().arg("foo", "bar"); } 

and gives me error:

test.rs:32:30: 32:35 error: trait `core::marker::sized` not implemented type `str` [e0277] test.rs:32     struct::new().arg("foo", "bar");                                              ^~~~~ test.rs:32:30: 32:35 note: `str` not have constant size known @ compile-time test.rs:32     struct::new().arg("foo", "bar"); 

the error not spurious.

the raw representation of trait object (std::raw::traitobject):

#[repr(c)] pub struct traitobject {     pub data: *mut (),     pub vtable: *mut (), } 

the actual data of object behind single pointer.

but how dynamically sized types? taking slice (&[t]) example, of form:

#[repr(c)] pub struct slice<t> {     pub data: *const t,     pub len: usize, } 

this reference two words: pointer start of slice and number of elements in slice.

the size of &t not constant. if t sized, &t , box<t> 1 word, if t not sized, &t , box<t> two words.

let word = std::mem::size_of::<usize>();  // references sized types: 1 word. assert_eq!(std::mem::size_of::<&()>(), 1 * word); assert_eq!(std::mem::size_of::<&u8>(), 1 * word); assert_eq!(std::mem::size_of::<&string>(), 1 * word);  // references unsized types: 2 words. assert_eq!(std::mem::size_of::<&[u8]>(), 2 * word); assert_eq!(std::mem::size_of::<&str>(), 2 * word); assert_eq!(std::mem::size_of::<&std::path::path>(), 2 * word); 

what impact of this? well, mentioned earlier, definition of trait objects requires data pointer 1 word long. store dynamically sized type require two words there; haven’t given thought practicalities of whether possible inflate trait objects have 2 words data (one of redundant in case of sized objects), might or might not be, language has made decision not support trait objects of dynamically sized types.

therefore: if wish create trait object, need of sized type, such &str, rather dynamically sized type such str. means things (x: &&str) &std::fmt::display;:

arg("foo", &"bar"); 

Comments

Popular posts from this blog

cakephp - simple blog with croogo -

How to group boxplot outliers in gnuplot -

bash - Performing variable substitution in a string -