2015-10-17 76 views
7

一个简单的程序来演示此行为:为什么Box <T>的特征实现与Fn()冲突?

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); 
} 

编译失败:

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 

我的问题是:

  1. As far as I can tellBox<T>没有实现Fn()特质。那么为什么上面的例子失败?
  2. 什么是我想要做的正确实施?

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

回答

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, _:()) { } 
} 
+2

感谢克里斯您的回复,但恐怕我还没有得到它。你能解释一下Rust在这种情况下认为它会冲突的原因吗?例如,如果我正确理解你的解释,任何容器,让我们说'Arc '也应该冲突,因为'T'可以实现'CanSpeak'和'Arc '可以实现'Fn()'。但在我的例子中用'Arc'代替'Box'工作得很好。 – Vikas

+3

有*没什么特别的。这只是为了可以重叠的特征提供了两个通用实现。 –

+0

那么为什么'Arc'工作?在我的例子中,如果我用'Arc'代替'Box',它会编译时没有任何错误。 – Vikas