使用 HashSet::from_iter 时无法推断类型参数 `S` 的类型

chi*_*gjn 6 rust

我正在尝试解决一个涉及比较两组的在线挑战。我按照这个答案将我的Vec<i32>输出转换为HashSet

use std::collections::HashSet;
use std::iter::FromIterator;

struct Solution {}

impl Solution {
    pub fn solve(nums: Vec<i32>, k: i32) -> Vec<i32> {
        // todo, return dummy for now
        return vec![1, 2];
    }
}

fn main() {
    assert_eq!(
        HashSet::from_iter(Solution::solve(vec![1, 2, 3], 2)),
        HashSet::from_iter(vec![1i32, 2i32])
    )
}
Run Code Online (Sandbox Code Playgroud)

由于我还不明白的原因,编译失败:

error[E0282]: type annotations needed
  --> src/main.rs:15:9
   |
15 |         HashSet::from_iter(Solution::solve(vec![1, 2, 3], 2)),
   |         ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `S` declared on the struct `HashSet`
Run Code Online (Sandbox Code Playgroud)

它适用于 HashSet::from_iter(vec![1i32, 2i32])

我尝试添加类型注释HashSet::from_iter::<Vec<i32>>,但无济于事。我也阅读了源代码实现,但仍然无法弄清楚是什么让编译器抱怨。

我可以通过显式声明或HashSet使用 for 循环和inserts来解决它,但我想了解这里发生了什么。

我正在使用 Rust 1.43.1。

Eva*_*van 12

我相信Kitsu 的答案是微妙错误的,因为它表明 Rust 无法推断 的类型,因为这里可能是为收集不同类型的T类型实现的迭代器(最后会详细介绍)。PT

到底发生了什么

事实上,type Sin的类型推断HashSet<T, S>与 的类型无关T。问题是您的程序中没有任何信息允许编译器推断S.

添加类型参数足以解决歧义是正确的:

HashSet::<i32>::from_iter(vec![1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

这与您指定的实际类型无关事实上,这也有效:

HashSet::<_>::from_iter(vec![1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

原因是标准库中的定义HashSet包含默认类型S

pub struct HashSet<T, S = RandomState> {
    base: base::HashSet<T, S>,
}
Run Code Online (Sandbox Code Playgroud)

通过编写,HashSet::<_>::from_iter(vec![1, 2, 3]);您可以告诉编译器它应该使用 的默认类型S,即RandomState.

那么多个实现呢?

Kitsu 的回答指出,类型推断失败,S因为可能有FromIterator. 这是不正确的,但拥有多个实现可能会导致类型推断失败T

考虑这个例子:

HashSet::<i32>::from_iter(vec![1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

这会导致类型推断失败;请注意,这是推断失败T,而不是S

HashSet::<_>::from_iter(vec![1, 2, 3]);
Run Code Online (Sandbox Code Playgroud)

指定类型可以解决这种歧义:

let x = HashSet::<String>::from_iter(vec![Empty, Empty]);
Run Code Online (Sandbox Code Playgroud)

感谢 Rust Discord 上的 matt1992 帮助我了解这里到底发生了什么。

  • 自从我问这个问题以来,我写了更多的 Rust,当谈到原因时,这个答案似乎确实是准确的。事实上,在缺少多个 from_iter impl 的情况下,rust 会自动解析 T。@Evan Rust 无法推断使用默认 S = RandomState 是否有原因? (2认同)