由于不满足 trait bound,无法在 Option 上调用方法,需要是迭代器

问题描述

我知道这里的 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 可以应用,如果特征绑定 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>

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