Search code examples
rust

Type annotation when using macros assert_eq! and vec! in Rust


Is it possible to give the compiler type hints in this example using only macros?

Using two macros assert_eq! and vec! compiler gives this error:

error[E0282]: type annotations needed
 --> src/lib.rs:6:9
  |
6 |         assert_eq!(chop(&vec![]), vec![]); // error[E0282]: type annotations needed
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type

Here is the example code (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=83886decff48ece2aca3bdb37f7f4d0e):

#[cfg(test)]
mod tests {
    #[test]
    fn test_chop() {
        assert_eq!(chop(&vec![]), Vec::<&[u32]>::new()); // this works
        assert_eq!(chop(&vec![]), vec![]); // error[E0282]: type annotations needed
        assert_eq!(chop(&vec![1, 1]), vec![[1, 1]]);
        assert_eq!(chop(&vec![1, 2, 3, 4]), vec![[1, 2], [3, 4]]);
    }


    fn chop(rolls: &Vec<u32>) -> Vec<&[u32]> {
        rolls.chunks(2).collect()
    }
}

Solution

  • Distilling the problem down gets you to this:

    fn main() {
        let rolls: Vec<&[u32]> = vec![];
        if rolls != vec![] {
            panic!();
        }
    }
    
    error[E0283]: type annotations needed
     --> src/main.rs:3:14
      |
    3 |     if rolls != vec![] {
      |              ^^ cannot infer type for type parameter `U`
      |
      = note: multiple `impl`s satisfying `&[u32]: PartialEq<_>` found in the following crates: `alloc`, `core`:
              - impl<A, B> PartialEq<&B> for &A
                where A: PartialEq<B>, A: ?Sized, B: ?Sized;
              - impl<A, B> PartialEq<&mut B> for &A
                where A: PartialEq<B>, A: ?Sized, B: ?Sized;
              - impl<T, U, A> PartialEq<Vec<U, A>> for &[T]
                where A: Allocator, T: PartialEq<U>;
              - impl<T, U, N> PartialEq<[U; N]> for &[T]
                where the constant `N` has type `usize`, T: PartialEq<U>;
      = note: required for `Vec<&[u32]>` to implement `PartialEq<Vec<_>>`
    

    The ambiguity lies not in comparing the Vecs but rather comparing their elements. The compiler is trying to satisfy &[u32] == _ where _ is some placeholder type you're asking the compiler to infer. However there are multiple types that _ could be, and thus it emits an ambiguity error.

    You can keep the macro but give it a type hint like this:

    assert_eq!(chop(&vec![]), vec![] as Vec<&[_]>);
    

    Or potentially change your assert to assert!(... .is_empty()).