No type inference for tuples

I got two functions:

fn foo() -> i32 {
    let i;
    i = 1;
    i
}

(Rust Playground)
and

fn bar() -> (i32, i32) {
    let i;
    i.0 = 1;
    i.1 = 2;
    i
}

(Rust Playground)

Rust compiler (1.48) complains about bar that it needs type annotation for i, but it's seems to be totally fine with no annotations for foo.

Is it just a compiler imperfection or there is some reason why second case has no automatic type inference?

Even if you add a type annotation to the second example:

fn bar() -> (i32, i32) {
    let i: (i32, i32);
    i.0 = 1;
    i.1 = 2;
    i
}

it still fails to compile:

error[E0381]: assign to part of possibly-uninitialized variable: `i`
 --> src/lib.rs:3:5
  |
3 |     i.0 = 1;
  |     ^^^^^^^ use of possibly-uninitialized `i`

If you fix this error by initializing the whole value, then the type is inferred correctly:

fn bar() -> (i32, i32) {
    let i;
    i = (1, 2);
    i
}

So the error in the original code was misleading; the real problem is not that the type is unknown but that it is not possible to initialize a tuple in this way.

3 Likes

Or, to put it differently, in the second snippet, you have assignments and not initialization.

This is really just a limitation of the type inference algorithm. Any struct or tuple field access requires the accessed type to be fully inferred at that point.

This is why the example with the explicit type annotation passes type inference (it just fails borrowck because that does not support partially reinitializing a variable by reinitializing each of its fields – another rather arbitrary limitation that could in theory be lifted).

Those are the same thing. An assignment initializes its destination.

1 Like