Explicit type annotation for generic constructor of a generic type

Mikhail Borisov

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)
Shepmaster

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);
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Generic constructor for generic type in Rust

Calling constructor of generic type?

Calling constructor of a generic type

Generic type as a constructor parameter

Usage of generic type for explicit conversion

Explicit and implicit cast with generic type

Annotation to make available generic type

How to pass a type (generic) to an annotation?

Use generic type in class constructor

Calling constructor of generic type in TypeScript

Overloading constructor with a generic type in java

generic type of child class constructor

Instantiate generic type with constructor arguments?

How to use constructor of Generic type

Specify repeated generic type in constructor?

Return constructor of generic type in TypeScript

Generic constructor allow int type

Extending a generic type with a constructor function

Get the explicit type of a generic parameter at runtime in Scala

How to instantiate a generic record with explicit type parameters?

Explicit Casting Generic to Another Type in C#

Converting explicit type to T in generic method

Cast unknown object to generic interface of interface (from initially explicit generic type of generic collection type of type)

Why does giving explicit type arguments to a non-generic method or constructor compile?

How to work with generic type array and generic type class as parameter in constructor?

Java generic type bounded to classes with specific annotation

Python 3.7: check if type annotation is "subclass" of generic

How can I get a generic type annotation

How to parse Java annotation in generic type?