意外 "method not found" 编译器错误

Unexpected "method not found" compiler error

这个问题源于我(在一个学习 Rust 的玩具项目中)使用 itertoolscartesian_product 和 Rayon 的 into_par_iter。我的问题不是关于这个特定代码,而是关于阅读 rustc 错误消息和 Rust 库文档的问题。

这按预期工作:

fn main() {
    let it = 0..15;
    it.into_par_iter().for_each(|x| println!("{:?}", x));
}

但下面的代码无法编译并显示错误。 cartesian_product 返回的 Product 的文档包括 Iterator 的实现,所以我希望 into_par_iter 方法调用可以进行类型检查,但事实并非如此。

这是失败代码和生成的错误消息:

fn main() {
    let it = (0..15).cartesian_product(0..8);
    it.into_par_iter().for_each(|x| println!("{:?}", x));
}

Compiling iters v0.1.0 (D:\rust\iters)
error[E0599]: no method named `into_par_iter` found for struct `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>` in the current scope
   --> src\main.rs:8:8
    |
8   |       it.into_par_iter().for_each(|x| println!("{:?}", x));
    |          ^^^^^^^^^^^^^ method not found in `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>`
    |
   ::: D:\rust\dot.cargo\registry\src\github.com-1ecc6299db9ec823\itertools-0.9.0\src\adaptors\mod.rs:288:1
    |
288 | / pub struct Product<I, J>
289 | |     where I: Iterator
290 | | {
291 | |     a: I,
...   |
294 | |     b_orig: J,
295 | | }
    | | -
    | | |
    | |_doesn't satisfy `_: rayon::iter::IntoParallelIterator`
    |   doesn't satisfy `_: rayon::iter::ParallelIterator`
    |
    = note: the method `into_par_iter` exists but the following trait bounds were not satisfied:
            `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
            which is required by `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
            `&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
            which is required by `&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
            `&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
            which is required by `&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`

itertools::Itertools::cartesian_product returns a value of type itertools::Product,实现标准的 Iterator.

但是,Rayon 不能只使用任何实现 Iterator 的类型——它还必须实现 rayon::ParallelIterator。 Rayon 恰好为大多数 std 迭代器提供 ParallelIterator 的实现,但它不能在不依赖于另一个板条箱(如 itertools)的情况下为另一个板条箱中的结构实现它们。同样,itertools 无法在不依赖于 rayon.

的情况下为其类型实现 rayon::ParallelIterator

相反,您可以使用 Rayon 的 API:

自己复制 Itertools::cartesian_product 的功能
use rayon::iter::{ParallelIterator, IntoParallelIterator};

fn main() {
    (0..15).into_par_iter()
        .flat_map(|i| (0..8).into_par_iter().map(move |j| (i, j)))
        .for_each(|x| println!("{:?}", x));
}

或者,您可以从长度为 (15 * 8) 的迭代器开始,然后使用除法和余数将其分解为元组:

use rayon::iter::{ParallelIterator, IntoParallelIterator};

fn main() {
    let it = (0 .. 15 * 8).into_par_iter().map(|x| (x / 8, x % 8));
    it.for_each(|x| println!("{:?}", x));
}