graydon/rust — Issue #1451: bare fn types in record unification produces unexpected errors
Author: nikomatsakis
Created: 2012-01-07 00:41:15+00:00
State: open

In the following source:
```
type T = { mutable f: fn@() };
type S = { f: fn@() };

fn fooS(t: S) {
}

fn fooT(t: T) {
}

fn bar() {
}

fn main() {
let x: fn@() = bar;
fooS({f: x});
fooS({f: bar});

let x: fn@() = bar;
fooT({mutable f: x});
fooT({mutable f: bar});
}
```
the last call to `fooT()` results in an error:
```
/Users/nmatsakis/tmp/foo.rs:20:9: 20:25 error: mismatched types: expected `T` but found `{f: mutable fn()}` (types differ)
/Users/nmatsakis/tmp/foo.rs:20 fooT({mutable f: bar});
```
I believe this is because the field `f` is immutable and hence unified as invariant. This is kind of surprising to the user, though. The "right" fix is probably a bit involved though. If we were to get rid of bare function types, we'd be able to handle this, but it requires an improvement to the type checker (bounded type variables, since you don't know the type to assign to the bare function till later).