Rust 带有未装箱闭包的错误消息

Rust 带有未装箱闭包的错误消息,rust,Rust,这个使用unbox闭包的小FizzBuzz程序给出了一个相当神秘的错误消息 fn fizzbuzz<F: Fn(i64) -> bool>(n: i64, f: F, fs: &str, b: F, bs: &str) { for i in range(1i64, n+1) { match (f(i), b(i)) { (true, true) => println!("{:3}: {}{}", i, fs,

这个使用unbox闭包的小FizzBuzz程序给出了一个相当神秘的错误消息

fn fizzbuzz<F: Fn(i64) -> bool>(n: i64, f: F, fs: &str, b: F, bs: &str) {
    for i in range(1i64, n+1) {
        match (f(i), b(i)) {
            (true, true) => println!("{:3}: {}{}", i, fs, bs),
            (true, _)    => println!("{:3}: {}", i, fs),
            (_, true)    => println!("{:3}: {}", i, bs),
            _            => (),
        }
    }
}

fn main() {
    fizzbuzz(30,
             |&: i: i64| { i % 3 == 0 }, "fizz",
             |&: j: i64| { j % 5 == 0 }, "buzz");
}
错误消息:

<anon>:15:14: 15:40 error: mismatched types: expected `closure[<anon>:14:14: 14:40]`, found `closure[<anon>:15:14: 15:40]` (expected closure, found a different closure)
<anon>:15              |&: j: i64| { j % 5 == 0 }, "buzz");
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

有人能描述一下错误吗?谢谢。

每个未装箱的闭包定义都会创建一个完全不同的类型。这使得main中定义的每个闭包都具有不同的类型。另一方面,fizzbuz函数要求传递给它的每个闭包都是相同的类型F。如果将fizzbuzz的签名更改为:

fn fizzbuzz<F: Fn(i64) -> bool, G: Fn(i64) -> bool>(n: i64, f: F, fs: &str, b: G, bs: &str)
您的代码将进行打字检查


基本上,bool>语法不会为实现trait参数Fni64->bool的类型创建通配符,而是声明一个类型,该类型必须满足trait参数,并且在使用它的任何地方都是相同的类型。未绑定的闭包定义必须是不同的类型,这既是因为可以封装不同的环境,也是因为它们分派给不同的函数,即每个函数都有不同的主体。因此,fizzbuzz需要两个不同的类型参数来适应这两种闭包类型。

这段代码说明了问题的本质:

fn show_both<S: Show>(x: S, y: S) {
    println!("{} {}", x, y);
}
但这不是:

let x: i32 = 10;
let y: f64 = 20.0;
show_both(x, y);
这是很自然的:您指定这两个参数必须是相同的类型,即使这种类型可以是任意的,只要它实现Show

您的代码中基本上有相同的内容:

fn fizzbuzz<F: Fn(i64) -> bool>(n: i64, f: F, fs: &str, b: F, bs: &str)

请包括回答您的问题所需的所有详细信息,即问题正文中的代码。问题不应该依赖于外部链接,因为它们往往会在长期内中断,而我们正试图建立一个长期资源。干杯。请在您的问题中直接包含相关且仅相关的代码和错误消息,而不是要求人们单击可能不可信的链接。
fn fizzbuzz<F: Fn(i64) -> bool>(n: i64, f: F, fs: &str, b: F, bs: &str)
fn fizzbuzz<F1, F2>(n: i64, f: F1, fs: &str, b: F2, bs: &str)
    where F1: Fn(i64) -> bool,
          F2: Fn(i64) -> bool