简体   繁体   中英

Cannot infer type for generic type parameter in struct

I'm currently trying to implement base64 encoding/decoding in rust as part of a larger project and needed a data structure for mapping the base64 character set to ASCII and vice versa. I found a barebones implementation of a bidirectional HashMap in this StackOverflow answer , but since I need the base64 map to be a global variable in order for both encode/decode functions to access it, I can't just add the character mappings one by one. So I added another function to the BidiMap implementation that does it in one batch (other function implementations are the same as in the link above):

impl<A, B> BidiMap<A, B>
where
  A: Eq + Hash,
  B: Eq + Hash,
{

// ...

  pub fn from_array_with_u8_indices(values: &[B]) -> BidiMap<u8, B>
    where B: Copy,
  {
    if values.len() > u8::MAX as usize + 1 {
      panic!("This function should only be called with an array whose indices fit into an u8.");
    }
    let mut map: BidiMap<u8, B> = BidiMap::new();

    for i in 0..values.len() {
      map.insert(i as u8, values[i]);
    }

    map
  }

// ...

}

I then call this function in another file, base64.rs:

use crate::datastructures::bidi_map::BidiMap;

const base64_values: [u8; 65] = [
  0x41, 0x42, 0x43, ... , 0x3D,
];
const base64_map: BidiMap<u8, u8> = BidiMap::from_array_with_u8_indices(&base64_values);

But when I try to compile this code, I get the error

error[E0282]: type annotations needed
  --> src/encodings/base64.rs:10:37
   |
10 | const base64_map: BidiMap<u8, u8> = BidiMap::from_array_with_u8_indices(&base64_values);
   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `A`

Even though I specified the types for A and B with BidiMap<u8, u8> . I am pretty new to programming in rust and with generics in general, so it could be that I'm missing something really obvious, but I can't figure out what the solution to this problem is. I've already tried to change the function signature and implementation to return Self instead of BidiMap<u8, B> , but then it complained about not being able to cast the array indices to a generic type A when calling map.insert() .

Here is a minimal example to reproduce your issue.

As you noted, the return type for from_array_with_u8_indices is indeed correctly inferred.

However, the concrete type for BidiMap::from_array_with_u8_indices cannot be inferred because the method is implemented for BidiMap<A, B> . The return type is not related to this type.

Two possible fixes:

Specify the concrete type explicitly using the turbofish syntax:

let map = BidiMap::<u8, u8>::from_array_with_u8_indices(&base64_values);

Create a specific implementation for the type you know you are returning:

impl<B> BidiMap<u8, B>
where
    B: Eq + Hash,
{
    pub fn from_array_with_u8_indices(values: &[B]) -> Self
    where
        B: Copy,
    {
        let mut map: BidiMap<u8, B> = BidiMap::new();
        //...
        map
    }
}

in which case you don't need to specify the type at all:

let base64_map = BidiMap::from_array_with_u8_indices(&base64_values);

Example of working code in the playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM