2015-10-17 75 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