2016-04-16 5 views
1

In dem folgenden Programm (play) bietet die FooBar-Eigenschaft die bar-Methode, aber der tatsächliche Typ des Objekts, das von bar zurückgegeben wird, scheint ausgeblendet zu sein. Wenn ich ein Typ-Argument anstelle eines zugeordneten Typs verwende, funktioniert es (play).Typ Anmerkungen erforderlich - Warum werden zugeordnete Typen anders behandelt?

Warum werden zugeordnete Typen anders behandelt? Oder mache ich es falsch?

use std::ops::DerefMut; 

pub trait FooBar: Sized { 
    type Assoc: Sized + DerefMut<Target=Self>; 

    fn foo(&mut self) -> Option<Self::Assoc>; 

    fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc> { 
     unimplemented!() 
    } 
} 

#[derive(Debug)] 
struct Test(u32); 

impl FooBar for Test { 
    type Assoc = Box<Test>; 
    fn foo(&mut self) -> Option<Self::Assoc> { 
     unimplemented!() 
    } 
} 

fn main() { 
    let mut tt = Test(20); 
    let tt_foo: Box<Test> = tt.foo().unwrap(); // this is ok 
    let tt_bar: Box<Test> = FooBar::bar(Box::new(tt)).unwrap(); // but not this 
    assert_eq!(tt_bar.0, 20); 
} 

Antwort

4

Wenn Ihre Methode ist

fn bar(mut this: Self::Assoc) -> Result<Self::Assoc, Self::Assoc> 

und Sie versuchen, es zu nennen mit

FooBar::bar(Box::new(tt)) 

how Rust wissen soll, welche Art Self ist? Box::new(tt) ist Self::Assoc richtig, aber Sie können Self davon nicht erhalten, mehrere Typen könnten die gleiche Assoc haben.

Und das ist, was rustc beschwert sich über:

Typenannotationen erforderlich

Sie müssten mit Anmerkungen versehen, welche Art Self ist:

let tt_bar: Box<Test> = <Test as FooBar>::bar(Box::new(tt)).unwrap(); 

oder äquivalent:

let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap(); 
1

Das Problem besteht darin, dass Sie versuchen, über das Merkmal auf den zugeordneten Typ zuzugreifen. Sie können es nur von einem Typ zuzugreifen, die das Merkmal implementiert, wie aus Test:

let tt_bar: Box<Test> = Test::bar(Box::new(tt)).unwrap(); 

FooBar::Assoc kein konkreter ist, so dass Sie es nicht verwenden können. Wenn Sie FooBar für Test implementiert, gibt man Test::Assoc einen konkreten Typen, der zugänglich ist:

type Assoc = Box<Test>; 

In dem Code mit dem generischen Typ wurde eine neue Kopie von FooBar::bar mit konkreter erstellt. Da Sie eine Box<Test> angefordert, die Signatur der neuen Funktion wäre dies:

fn bar(mut this: Box<Test>) -> Result<Box<Test>, Box<Test>> 

Box<Test> ein konkreter Typ ist, so dass es funktioniert.

Verwandte Themen