Skip to content

Instantly share code, notes, and snippets.

@briangoetz
Created November 25, 2013 22:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save briangoetz/7650431 to your computer and use it in GitHub Desktop.
Save briangoetz/7650431 to your computer and use it in GitHub Desktop.
Flow typing
Proponents of "flow typing" have suggested, in code like this:
if (foo instanceof Bar) {
((Bar) foo).barMethod();
}
"why not just" allow the developer to elide the cast to Bar? Implicit in this question is the assumption that this is a very simple feature.
Like everything else, the easy cases are easy. The key question to ask is, under such a scheme, if the static type of foo outside the if-block is Moo, what is the static type of foo inside the if block?
One obvious, but wrong, candidate is Bar; this means that foo could no longer be used as a Moo:
if (foo instanceof Bar) {
...
foo.mooMethod(); // compile error: mooMethod() not a member of Bar
}
The less-wrong answer is an intersection type: (Moo & Bar). Now, imagine this overloading of existing methods:
void m(Moo m) { ... }
void m(Bar b) { ... }
and we have existing code like this:
if (foo instanceof Bar) {
m(foo);
...
}
But if we reinterpret the static type of foo as Moo & Bar, this code no longer compiles, due to an ambiguity in overload resolution. So this language change, as envisioned, is not source-compatible. Oops.
Now, one could layer arbitrarily complicated new rules for overload resolution to try and "fix" this problem, but now we're well outside the territory of an "easy" feature.
@mikaelgrev
Copy link

Ah, OK. Thanks for clearing that up.

I do of course know the difference but I didn't think that would matter here. Luckily you did. :)

Cheers,
Mikael

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment