Explicit type annotation for generic generic type constructor

I am writing a Rust binding for C library. It implements an object that can be created from different source objects, possibly keeping some links inside. I want the Rust type to apply the secure ownership policy, so the wrapper structure is a generic, parameterized type of 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 a problem arises: both the structure and the constructor are independently parameterized. Although a constructor type parameter can be inferred from its arguments, a struct parameter is not used in the constructor and cannot be inferred. So the naive way to call the 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 parameter of an arbitrary type:

 let a = Foobar::<()>::from_nowhere(); let b = Foobar::<()>::from_orange(&mut fruit); let c = Foobar::<()>::from_callback(|x| x*x); 

... these are all kinds of ugly. Another way to solve the problem would be to turn the constructors into free functions, although this would be (inaccurate) non-idiomatic.

The question is, am I missing something? The design seems to be incorrect. What would be the right way to create this type to get away with the same generic level?


Minimal reproducible example in a rust arena

For reference, my compiler version:

 $ rustc --version rustc 1.1.0-dev (built 2015-04-26) 
+5
source share
1 answer

As I understand it, your source code is parameterized to T , but you have methods that want to specify a parameter. The trick is not to have something in common for these cases. Instead, try creating custom 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); } 
+7
source

All Articles