编译器说要添加类型参数,但我认为在这种情况下我不能

Compiler says to add type parameters, but I don't think I can in this context

编译器抱怨需要类型注释。我能够通过创建一个带有类型参数的未使用变量来修复它,在下面的代码片段中注释掉了。不过,这感觉像是一个奇怪的解决方法,有没有办法在不需要这样做的情况下添加类型参数?看起来 rust 应该知道 key 的类型,因为 Map 是定义的类型。

type Map = Arc<DashMap<[u8; 32], Session>>;

pub struct SessionManager {
    map: Map,
    db_wtx: WriteTx,
    db_rtx: ReadTx,
}

impl SessionManager{
    pub fn logout(&self, token: &str) {
        if let Ok(decoded_vec) = base64::decode(token) {
            if let Ok(key) = decoded_vec.try_into() {
                //let _typed_key: [u8; 32] = key;
                self.map.remove(&key);
            }
        }
    }
}

错误消息:

error[E0282]: type annotations needed
   --> src/login_handler.rs:244:14
    |
244 |             if let Ok(key) = decoded_vec.try_into() {
    |                       ^^^    ---------------------- this method call resolves to `Result<T, <Self as TryInto<T>>::Error>`
    |                       |
    |                       cannot infer type

编辑:为清楚起见,我使用的是 dashmap crate,它试图在允许多线程访问的同时密切模仿 std::hashmap 的 api。

rustc 无法推断类型,因为 Map::remove()(假设您实际上是在谈论 HashMap,或 BTreeMap)不将 &K 作为参数类型(其中 K 是键类型),而是 Q 其中 Q: Borrow<K>。这允许更大的灵活性(例如,为 Strings 的映射传递 &str),但以更糟糕的推理为代价。

有几种选择:您可以指定 Ok 的类型:

if let Ok::<[u8; 32], _>(key) = decoded_vec.try_into()

这是一个 shorthand 用于:

if let Result::<[u8; 32], _>::Ok(key) = decoded_vec.try_into()

或者您可以使用 TryFrom 而不是 TryInto:

if let Ok(key) = <[u8; 32]>::try_from(decoded_vec)

如果您选择一个变量,请注意最好使用 _ 而不是另一个 underscore-prefixed 名称,如 _typed_key。这是因为 _ 不会移动值,但任何其他名称都会移动。这在这种情况下不相关,因为 [u8; 32]Copy,但仍然是一个很好的做法。