Sto scrivendo un binding Rust per una libreria C. Implementa un'entità che può essere costruita da diverse entità di origine, eventualmente salvando alcuni riferimenti internamente. Voglio che il tipo Rust imponga una politica di proprietà sicura, quindi la struttura del wrapper è generica, parametrizzata dal tipo del riferimento memorizzato.Annotazione esplicita del tipo per costruttore generico di tipo generico
struct Foobar<T> {
origin: T,
}
Poi ho implementare alcuni costruttori per il mio tipo Foobar
.
impl<T> Foobar<T> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin:() }
}
fn from_orange<F>(orange: &mut F) -> Foobar<&mut F>
where F: Orange
{
Foobar { origin: orange }
}
fn from_callback<F>(callback: F) -> Foobar<F>
where F: FnMut(u64) -> u64
{
Foobar { origin: callback }
}
}
E qui arriva il problema: sia la struct che il costruttore sono parametrizzati in modo indipendente. Mentre il parametro del tipo di costruttore può essere dedotto dai suoi argomenti, il parametro struct type non viene utilizzato nel costruttore e non può essere dedotto. Così, il modo ingenuo chiamare un costruttore
let a = Foobar::from_nowhere();
let b = Foobar::from_orange(&mut fruit);
let c = Foobar::from_callback(|x| x*x);
confonde rustc:
rustgen.rs:43:13: 43:33 error: unable to infer enough type information about `_`; type annotations required [E0282]
rustgen.rs:43 let a = Foobar::from_nowhere();
Esso può essere risolto fornendo un certo tipo di parametro arbitrario:
let a = Foobar::<()>::from_nowhere();
let b = Foobar::<()>::from_orange(&mut fruit);
let c = Foobar::<()>::from_callback(|x| x*x);
... che è tutto tipi di brutto. Un altro modo per risolvere il problema sarebbe quello di trasformare i costruttori in funzioni libere, anche se sarebbe (un po ') non idiomatico.
La domanda è: mi manca qualcosa? Il design sembra essere difettoso in qualche modo. Quale sarebbe il modo corretto di progettare questo tipo per farla franca con un solo livello di generici?
Minimal reproducible example on Rust playpen
Per riferimento, la mia versione del compilatore è:
$ rustc --version
rustc 1.1.0-dev (built 2015-04-26)
Grazie! Ciò di cui non mi rendevo conto era che è possibile avere più clausole "impl" per diverse parametrizzazioni. –