Deref coercion with traits

why doesn't deref coercion work here?

pub trait Pluralize {
    fn pluralize(&self) -> String;
}

impl Pluralize for &str {
    fn pluralize(&self) -> String {
        format!("{}es", self)
    }
}

fn main() {
    let s = String::from("Box");
    println!("{}", s.pluralize());
}

impl Pluralize for str { will work.

1 Like

yeah, thanks. I think I did it wrong. this works too(using self instead of &self)

pub trait Pluralize {
    fn pluralize(self) -> String;
}

impl Pluralize for &str {
    fn pluralize(self) -> String {
        format!("{}es", self)
    }
}

fn main() {
    let s = String::from("Box");
    println!("{}", s.pluralize());
}

The original version doesn't work because you have &str as the type implemented upon, and also &self as the receiver, so the method actually requires &&str.

Auto-(de)-referencing in method lookup proceeds as follows:

  1. Dereference the receiver repeatedly, obtaining the candidate types String and str (because String's Deref target type is str).
  2. For each such type, try referencing it.

This makes the final list of candidate types:

String, &String, &mut String, str, &str, &mut str

There's actually a specific reason it makes sense to stop here and not also try &&str: that type would require putting an &str on the stack and taking its address, whereas the others are all either existing values to be moved/copied, or references that Deref or DerefMut will return when invoked, so they don't require allocating any new addresses.

5 Likes