What is a concise way to inform the compiler of th

2020-02-15 03:57发布

问题:

I've come across an odd type inference problem that has me scratching my head a bit.

I'm implementing a generic trait on a struct for multiple types. I started with &str:

struct Bar<'a> {
    baz: &'a str,
}

trait Foo<T> {
    fn foo(&self) -> T;
}

impl<'a> Foo<&'a str> for Bar<'a> {
    fn foo(&self) -> &'a str {
        self.baz
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_str_a() {
        let bar = Bar { baz: "asd" };
        assert_eq!("asd", bar.foo());
    }
}

This works — the problem comes when I add another implementation for the u8 type:

struct Bar<'a> {
    baz: &'a str,
}

trait Foo<T> {
    fn foo(&self) -> T;
}

impl<'a> Foo<&'a str> for Bar<'a> {
    fn foo(&self) -> &'a str {
        self.baz
    }
}

impl<'a> Foo<u8> for Bar<'a> {
    fn foo(&self) -> u8 {
        8
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_str_a() {
        let bar = Bar { baz: "asd" };
        assert_eq!("asd", bar.foo());
    }

    #[test]
    fn test_u8() {
        let bar = Bar { baz: "asd" };
        assert_eq!(8 as u8, bar.foo());
    }
}

In this case, I get the following error:

error[E0283]: type annotations required: cannot resolve `Bar<'_>: Foo<_>`
  --> src/main.rs:28:31
   |
28 |         assert_eq!("asd", bar.foo());
   |                               ^^^

If I store the value in a variable it works:

let foo: &str = bar.foo();

In my production code, I do a lot of asserts and it would make things a bit messy. I've also tried bar.foo() as &str but that also fails as the compiler doesn't know bar.foo()'s type either. I'm trying to find a concise way for the compiler to know the type.

回答1:

Pass the type parameter to the trait using a turbofish (::<>):

assert_eq!("asd", Foo::<&str>::foo(&bar));

You could also use fully-qualified syntax to disambiguate which trait the method belongs to:

// This is "type-qualified" and equivalent to `Foo::<&str>::foo(&bar)`
assert_eq!("asd", <_ as Foo<&str>>::foo(&bar));

// This is "fully qualified"
assert_eq!("asd", <Bar as Foo<&str>>::foo(&bar));