Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type annotation required when using `as_ref()` in `assert_eq!()`

I'm using the new generic conversion traits in my code and experience reduced ergonomics. The code in question implements AsRef<str> for [Ascii] as you can see in the example.

Now I want to use v.as_ref() in assert_eq!() and expect that v.as_ref() returns a &str using the provided implementation because the second argument to assert_eq!() is of type &str.

There is no implementation of AsRef<String> for [Ascii] so in my opinion only one implementation of PartialEq comes into play: PartialEq<str> for &str.

The compiler doesn't follow my explanation and complains about required type annotations. How can I avoid the explicit annotation and why can't the compiler figure out the correct implementation of AsRef<_>?

Thanks

#![feature(convert)]

struct Ascii { chr: u8 }

impl AsRef<str> for [Ascii] {
    fn as_ref(&self) -> &str {
        unsafe { ::std::mem::transmute(self) }
    }
}

fn main() {
    let v = [Ascii { chr: 65 }, Ascii { chr: 66 }];
    assert_eq!(v.as_ref(), "AB");
    // Workaround: explicit type annotation.
    //assert_eq!(AsRef::<str>::as_ref(&v[..]), "AB");
}

Playpen link: http://is.gd/ZcdqXZ

<anon>:15:18: 15:26 error: type annotations required:
    cannot resolve `[Ascii] : core::convert::AsRef<_>` [E0283]
<anon>:15     assert_eq!(v.as_ref(), "AB");
                       ^~~~~~~~
like image 566
Thomas Avatar asked Nov 09 '22 17:11

Thomas


1 Answers

Look at the listed implementors of AsRef in the documentation in more detail and you find that there is another implementation that collides there: impl<T> AsRef<[T]> for [T]. So it can’t decide whether v.as_ref() should be of type &str or &[Ascii].

like image 112
Chris Morgan Avatar answered Dec 05 '22 04:12

Chris Morgan