I'm writing a Rust binding for a C library. It implements an entity that can be constructed from different source entities, possibly saving some references internally. I want the Rust type to enforce a safe ownership policy, thus the wrapper struct is generic, parameterized by the type of the stored reference.
struct Foobar<T> {
origin: T,
}
Then I implement some constructors for my Foobar
type.
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 }
}
}
And here comes the problem: both the struct and the constructor are independently parameterized. While the constructor type parameter can be inferred from its arguments, the struct type parameter is not used in the constructor and cannot be inferred. Thus, the naive way to call a constructor
let a = Foobar::from_nowhere();
let b = Foobar::from_orange(&mut fruit);
let c = Foobar::from_callback(|x| x*x);
confuses 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();
It can be fixed by providing some arbitrary type parameter:
let a = Foobar::<()>::from_nowhere();
let b = Foobar::<()>::from_orange(&mut fruit);
let c = Foobar::<()>::from_callback(|x| x*x);
...which is all sorts of ugly. Another way to solve the problem would be to turn constructors into free functions, though it would be (kinda) non-idiomatic.
The question is, am I missing something? The design seems to be flawed in some way. What would be the proper way to design this type to get away with only one level of generics?
Minimal reproducible example on Rust playpen
For reference, my compiler version is:
$ rustc --version
rustc 1.1.0-dev (built 2015-04-26)
As I understand it, your original code is parameterized on T
, but you have methods that want to specify the parameter. The trick is to not have a generic for these cases. Instead, try creating specialized implementations for each interesting type:
// this is just an example. suppress unrelated warnings
#![allow(dead_code, unused_variables)]
struct Foobar<T> {
origin: T,
}
trait Orange {}
struct Grapefruit;
impl Orange for Grapefruit {}
impl Foobar<()> {
fn from_nowhere() -> Foobar<()> {
Foobar { origin: () }
}
}
impl<'a, F> Foobar<&'a mut F>
where F: Orange
{
fn from_orange(orange: &'a mut F) -> Foobar<&'a mut F> {
Foobar { origin: orange }
}
}
impl<F> Foobar<F>
where F: FnMut(u64) -> u64
{
fn from_callback(callback: F) -> Foobar<F> {
Foobar { origin: callback }
}
}
fn main() {
let mut fruit = Grapefruit;
// What I actually wanted to do
let a1 = Foobar::from_nowhere();
let b1 = Foobar::from_orange(&mut fruit);
let c1 = Foobar::from_callback(|x| x*x);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With