Florian Doyon
Florian Doyon

Reputation: 4186

Trait is not implemented for the type `&str` [E0277]

I have a trait definition for str where I define a function taking &self. If I call this function from main on a static &str, all is fine. If I call the same function from a function taking a trait object parameter, I am greeted with the following error: MyTrait is not implemented for the type&str[E0277]

I have a workaround at the end, but I am not clear on the costs, am I copying the string?

#[derive(Debug)]
struct Thingie{
 pub name: String, // rather than &a str for Thingie<'a>
}

trait MyTrait{
    fn to_thingie(&self)->Option<Thingie>;
}

impl MyTrait for str{
    fn to_thingie(&self)->Option<Thingie>{
        println!(">>MyTrait for str");
        Some(Thingie{name:self.to_string()})
    }
}


fn method_on_trait <T:MyTrait> (thing:T){
   let v= thing.to_thingie();
   println!("Method on trait: {:?}",v);
}

fn main(){
 println!("in main: {:?}","test".to_thingie());
 method_on_trait("test");
}

//TODO: Uncomment this for a fix. WHY?
//Is this creating a copy of the string or just transfering the binding?
// impl<'a> MyTrait for &'a str{
//     fn to_thingie(&self)->Option<Thingie>{
//         println!(">>MyTrait<'a> for &'a str");
//         (*self).to_thingie()
//     }
// }

Upvotes: 3

Views: 1901

Answers (1)

Paolo Falabella
Paolo Falabella

Reputation: 25844

You need to tell method_on_trait that it can work on unsized types and pass it a reference to T (not directly T, which at this point might not be sized and can't be passed by value). The first you can do adding the ?Sized "bound" to T, the second by making thing a &T.

fn method_on_trait<T: MyTrait + ?Sized> (thing: &T) {
   let v = thing.to_thingie();
   println!("Method on trait: {:?}",v);
}

What's going on here, is that MyTrait is only implemented for str, which is an unsized type. You try passing "test" (which is a &'static str) to method_on_trait in main, which leads to the E0277 error.

Your commented code is implementing MyTrait for &str, which makes your original code compile because you're indeed passing a &str to method_on_trait. There is no copying of the original string, &str is only basically a pointer to it plus a length info.

Upvotes: 3

Related Questions