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()
}
}
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 Vec
s 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())
.