Inference of return value

I can’t get my intuition to work with generics.

For this code

fn foo<X>() -> X
{
    1
}

I get error:

error[E0308]: mismatched types
 --> src/main.rs:4:5
  |
2 | fn foo<X>() -> X
  |                - expected `X` because of return type
3 | {
4 |     1
  |     ^ expected type parameter, found integral variable
  |
  = note: expected type `X`
             found type `{integer}`
  1. Why Rust can’t infer the integer type here?
  2. Outside of “don’t do this”, what Rust expects me to return here for this case? What is ‘type parameter’ and how can I write it in the function body?

Because it’s the caller that gets to decide what X is.

let f: f32 = foo();
let s: String = foo();
struct Bar(f32);
let b: Bar = foo();

All these must compile given the signature of foo. But they can’t, because 1 is not a f32, a String, or a Bar. Indeed, it is impossible to ever return from foo because you can’t assume anything about X inside it. The only thing the function could do is loop forever or terminate the program eg. by panicking.

2 Likes

With some struggles I was able to make it work:

fn foo<X>() ->X
where
X: From<i32>
{
    X::from(1)
}

And it, indeed, requires caller to annotate it:

let x:i32 = foo();
1 Like

Yes; now you have constrained the function so it can only be called on those types that can be constructed from an i32. Another way to pass the type parameter at the call site is by using the “turbofish operator”:

let x = foo::<i32>();

If you want the function to decide the return type, then you have to use -> impl Trait where Trait is some trait that the return type guarantees to implement.

3 Likes