Helping out the compiler with generic type inference


#1

I have a bit of code that looks like this:

trait State { fn do_stuff(); }

struct Parent<S: State> {
    builder: Builder<S>
}

fn parent<S: State>() -> Parent<S> {
    Parent { builder: Builder::new() }
}

So basically you can create a parent that holds a Builder<S> using a free-standing function. I use it like this:

struct MyStruct;

impl State for MyStruct {
    fn do_stuff() {
        parent()....
    }
}

Now, Rust cannot infer S in that call to parent(). I can call it like parent::<Self>(), or I can even change parent to:

fn parent<S: State>(_: &S) -> Parent<S> {
    Parent { builder: Builder::new() }
}

So even by adding a placeholder function argument Rust can now infer the correct type for S (namely: MyStruct). Is there any way I can get Rust to do this without having to explicitly adding ::<Self> or by adding Self as a dummy function argument?


#2

I don’t think it’s possible in this case, because in your example any version of parent() would be compatible. For inference to work there has to be clearly one and only one possible solution.

If for example you returned a specific version of Parent, then it should give a unique solution:

fn do_stuff() -> Parent<Self> {
    parent()
}

#3

Okay, that makes sense. I’ll try to refactored the code so the generic is in the return type or used at least once in the do_stuff methld itself.


#4

You could also make parent a method on either the State trait or another trait implemented for all State; either way you could then write Self::parent().


#5

Yes, indeed. I was hoping I wouldn’t need this additional reference to Self but it’s no big deal either :slight_smile: