由于不满足特征边界,无法在 Option 上调用方法,需要是迭代器

Method cannot be called on Option due to unsatisfied trait bounds, needs to be iterator

我知道这里的 cloned() 是不必要的,但我想知道为什么它要求 Values 实现 Iterator 特性。

最小可重现示例

#[derive(Debug, Clone)]
enum Values {
    Foo,
    Bar
}

fn f(mut values: impl Iterator<Item=Values>) {
    // (HERE) Why to clone Option<Values> should implement Iterator???
    if let Some(v1) = values.next().cloned() {
        if let Some(v2) = values.next() {
            println!("Foo");
        }
    }
}

fn main() {
    let mut values = vec![
        Values::Foo,
        Values::Bar
    ];
    
    f(values.into_iter());
}

错误

error[E0599]: the method `cloned` exists for enum `Option<Values>`, but its trait bounds were not satisfied
   --> src/main.rs:8:37
    |
8   |       if let Some(v1) = values.next().cloned() {
    |                                       ^^^^^^ method cannot be called on `Option<Values>` due to 
unsatisfied trait bounds
    |
    = note: the following trait bounds were not satisfied:
            `Option<Values>: Iterator`
            which is required by `&mut Option<Values>: Iterator`

游乐场 link

有两个适用的 cloned 函数,Iterator::clonedOption::cloned
Option::cloned 不适用于这种情况,因为它仅适用于 Option<&T> 等类型。在示例中,它是一个 Option<Value>,它不是引用。
Iterator::cloned 可以应用,如果 trait bound Option<Values>: Iterator 很满意,这就是为什么这是建议的一部分。 在此上下文中使用这两个函数都是错误的。

也许您打算使用 clone 函数,这确实是不必要的。

Option::cloned() 仅在内部值是引用时才定义。例如,如果参数是 values: impl Iterator<Item = &Values>,您可以调用它,这将使 next() 的结果成为 Option<&Values>

你的参数values: impl Iterator<Item = Values>意味着迭代器拥有这些值。当您遍历迭代器时,这些值将移出迭代器,因此不需要克隆。我认为这只是它作为最小可重现示例的产物。


该错误令人困惑,因为编译器试图通过建议您可以实现的特征来帮助您,这些特征确实具有 cloned() 方法,并且选择是:

  • Option<&T>
  • I 其中 I: Iterator<Item = &T>

不幸的是,它选择了一个不适用于您的情况。