为什么Box <T>的特征实现与Fn()冲突?

Vik*_*kas 7 generics traits rust

一个简单的程序来演示这种行为:

use std::boxed::Box;

struct Cow;

trait CanSpeak {
    fn speak(&self);
}

impl CanSpeak for Cow {
    fn speak(&self) {
        println!("moo");
    }
}

impl<F: Fn()> CanSpeak for F {
    fn speak(&self) {
        self();
    }
}

impl<T: CanSpeak> CanSpeak for Box<T> {
    fn speak(&self) {
        (**self).speak()
    }
}

fn lol_speak() {
    println!("lol")
}

fn lets_speak<T: CanSpeak>(t: & T) {
    t.speak();
}

fn main() {
    let cow = Cow;
    lets_speak( &cow );

    lets_speak( &lol_speak );

    let boxed_cow = Box::new(Cow);
    lets_speak( &boxed_cow );
}
Run Code Online (Sandbox Code Playgroud)

编译失败:

test.rs:15:1: 19:2 error: conflicting implementations for trait `CanSpeak` [E0119]
test.rs:15 impl<F: Fn()> CanSpeak for F {
test.rs:16     fn speak(&self) {
test.rs:17         self();
test.rs:18     }
test.rs:19 }
test.rs:15:1: 19:2 help: run `rustc --explain E0119` to see a detailed explanation
test.rs:21:1: 25:2 note: note conflicting implementation here
test.rs:21 impl<T: CanSpeak> CanSpeak for Box<T> {
test.rs:22     fn speak(&self) {
test.rs:23         (**self).speak()
test.rs:24     }
test.rs:25 }
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 据我所知 Box<T>,没有实现Fn()特质.那么为什么上面的例子失败了?
  2. 我正在尝试做什么的正确实现是什么?

我刚开始学习Rust.谢谢你的帮助.

Chr*_*gan 6

这两个做冲突,因为它是可能的类型Box<T>T执行CanSpeakBox<T>落实Fn().锈一致性规则并不是什么但什么可以.

下面是实现的一个例子Fn()Box<Cow>,这显然会爆炸的事情,如果它让你的两个通用的特点实现:

// (This attribute on the crate.)
#![feature(unboxed_closures, core)]

impl Fn<()> for Box<Cow> {
    extern "rust-call" fn call(&self, _: ()) { }
}

impl FnMut<()> for Box<Cow> {
    extern "rust-call" fn call_mut(&mut self, _: ()) { }
}

impl FnOnce<()> for Box<Cow> {
    type Output = ();
    extern "rust-call" fn call_once(self, _: ()) { }
}
Run Code Online (Sandbox Code Playgroud)

  • 它没有*特别之处.只是你为一个可以重叠的特征提供了两个通用实现. (3认同)
  • 谢谢克里斯的回复,但我恐怕还是没有得到它.你能解释一下什么使得`Box`在这种情况下特殊,Rust认为它可以冲突吗?例如,如果我理解你的解释正确,任何容器,让我们说'Arc <T>`也应该冲突,因为`T`可以实现`CanSpeak`和`Arc <T>`可以实现`Fn()`.但在我的例子中用'Arc`替换`Box`就可以了. (2认同)