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.
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.