Why can you compare a &str to a Cow<str> but not the other way around?

If you have a &str and a Cow<str> you can call Ord::cmp with the &str as the first argument and the Cow<str> as the second, but the other way around doesn't compile.

let s1 = "foo";
let s2 = std::borrow::Cow::Borrowed("foo");

// works
dbg!(s1.cmp(&s2));
// doesn't compile
dbg!(s2.cmp(&s1));

Playground Link

Is there a reason that it works this way? Or is there just an Ord implementation that can and should be added to the standard library?

1 Like

The first example takes advantage of automatic dereferencing - so &s2 gets automatically converted to an &str, since we're invoking the Ord implementation for str.

The second example is calling the Ord implementation for Cow<'_, str>, and so can't take advantage of this - there's no way to promote an &str to a Cow<'_, str> automatically.

However, this works:

fn main() {
    let s1 = "foo";
    let s2 = std::borrow::Cow::Borrowed("foo");
    
    // works
    dbg!(s1.cmp(&s2));
    // invokes `impl Ord for str`
    dbg!((*s2).cmp(s1));
}

This explicitly converts the s2 to &str, and then invokes the Ord implementation for &str.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.