2016-10-02 3 views
3

Ich habe eine nicht generische Struktur, die ein generisches Merkmal implementiert. Wenn ich eine Funktion auf der Struktur aufrufen, erhalte ich folgende Fehlermeldung:Aufruf einer spezifischen Merkmalsimplementierung für eine nicht generische Struktur

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 

Ich habe versucht Typenannotationen Hinzufügen und generische Parameterbindungen, aber ich bin offensichtlich etwas falsch zu machen; Ich kann es immer noch nicht kompilieren. Ich habe ähnlichen Code an anderer Stelle mit einer generischen Struktur, die funktioniert, vermutlich weil die generischen Grenzen, die von der Struktur und der Eigenschaft impl geteilt werden, dem Compiler ermöglichen, die tatsächliche Methodenimplementierung zum Aufruf zu bestimmen.

Der beste Weg, um das Problem zu veranschaulichen, ist mit einem reduzierten Beispiel:

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 `_` 
} 

Bitte der Armen Titel entschuldigen, aber es ist der beste Weg, ich weiß, wie das Problem zu beschreiben.

Antwort

6

Sie haben mehrere Möglichkeiten.

  1. Sie auf die spezifische Eigenschaft angeben können Sie die attach Methode aufzurufen.

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

    oder

    fn main() { 
        let mut cpu = Cpu::new(SimpleMemory, NoOpDebugger); 
        <NoOpDebugger as Debugger<SimpleMemory>>::attach(&mut cpu.debugger); 
    } 
    
  2. Sie können die attach Methode auf eine supertrait bewegen, die nicht generisch ist.

    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. Sie können ein PhantomData Mitglied NoOpDebugger hinzufügen und NoOpDebugger selbst generische machen, so daß jeder NoOpDebugger<M> nur Debugger<M> für die gleiche M implementiert. In Ihrem Beispiel wird die M für NoOpDebugger aus dem Aufruf an Cpu::new abgeleitet werden.

    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. Wenn die Implementierungen von Debugger hängen nicht von M, und wenn Sie nicht Debugger als Merkmal Objekt nicht verwenden, dann können Sie den Typ-Parameter auf die Methoden bewegen, die sie benötigen und lassen es auf die Methoden, die es nicht brauchen.

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