2016-10-02 66 views
3

我有一個非泛型結構實現了泛型特徵。當我呼籲結構的函數,我得到以下錯誤:在非泛型結構上調用特定的特質實現

error[E0282]: unable to infer enough type information about `_` 
    --> src/main.rs:35:18 
    | 
35 |  cpu.debugger.attach(); 
    |     ^^^^^^ cannot infer type for `_` 
    | 
    = note: type annotations or generic parameter binding required 

我已經嘗試添加類型的註釋和泛型參數綁定,但我明明做錯事;我仍然無法編譯它。我在其他地方有類似的代碼,它可以工作,這大概是因爲struct和trait impl共享的泛型邊界允許編譯器推斷調用的實際方法實現。

來說明這個問題的最好辦法是減少的例子:

struct Cpu<M: Memory, D: Debugger<M>> { 
    mem: M, 
    debugger: D, 
} 

impl<M: Memory, D: Debugger<M>> Cpu<M, D> { 
    fn new(mem: M, debugger: D) -> Self { 
     Cpu { 
      mem: mem, 
      debugger: debugger, 
     } 
    } 
} 

trait Memory {} 

struct SimpleMemory; 

impl Memory for SimpleMemory {} 

trait Debugger<M: Memory> { 
    fn attach(&mut self) {} 
    fn step(mem: &M) {} 
} 

struct NoOpDebugger; 

impl<M: Memory> Debugger<M> for NoOpDebugger {} 

fn main() { 
    let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger); 
    cpu.debugger.attach(); // <-- cannot infer type for `_` 
} 

請原諒可憐的稱號,但它是我知道怎麼描述這個問題的最好辦法。

回答

6

你有幾個選擇。

  1. 您可以指定想要調用attach方法的特定特徵。

    fn main() { 
        let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger); 
        Debugger::<SimpleMemory>::attach(&mut cpu.debugger); 
    } 
    

    fn main() { 
        let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger); 
        <NoOpDebugger as Debugger<SimpleMemory>>::attach(&mut cpu.debugger); 
    } 
    
  2. 您可以將attach方法移到supertrait是不通用的。

    trait DebuggerBase { 
        fn attach(&mut self) {} 
    } 
    
    trait Debugger<M: Memory>: DebuggerBase { 
        fn step(mem: &M) {} 
    } 
    
    impl DebuggerBase for NoOpDebugger {} 
    impl<M: Memory> Debugger<M> for NoOpDebugger {} 
    
  3. 您可以將PhantomData成員添加到NoOpDebuggerNoOpDebugger本身一般,讓每個NoOpDebugger<M>只實現Debugger<M>爲同一M。在你的例子中,MNoOpDebugger將從Cpu::new的調用中推斷出來。

    use std::marker::PhantomData; 
    
    struct NoOpDebugger<M>(PhantomData<M>); 
    
    impl<M: Memory> Debugger<M> for NoOpDebugger<M> {} 
    
    fn main() { 
        let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger(PhantomData)); 
        cpu.debugger.attach(); 
    } 
    
  4. 如果Debugger的實現不依賴於M,如果你不使用Debugger爲特徵的對象,那麼你可以在類型參數移動到需要它的方法和忽略它不需要它的方法。

    trait Debugger { 
        fn attach(&mut self) {} 
        fn step<M: Memory>(mem: &M) {} 
    } 
    
相關問題