On 3/23/2022 10:51 PM, Dan Smith wrote:
On Mar 22, 2022, at 5:56 PM, Dan Smith <daniel.sm...@oracle.com> wrote:
- Variable types: I don't see a good way to get the equivalent of an
'IdentityObject' type. It would involve tracking the 'identity'
property through the whole type system, which seems like a huge
burden for the occasional "I'm not sure you can lock on that" error
message. So we'd probably need to be okay letting that go.
Fortunately, I'm not sure it's a great loss—lots of code today seems
happy using 'Object' when it means, informally, "object that I've
created for the sole purpose of locking".
- Type variable bounds: this one seems more achievable, by using the
'value' and 'identity' keywords to indicate a new kind of bounds
check ('<identity T extends Runnable>'). Again, it's added
complexity, but it's more localized. We should think more about the
use cases, and decide if it passes the cost/benefit analysis. If not,
nothing else depends on this, so it could be dropped. (Or left to a
future, more general feature?)
Per today's discussion, this part seems to be the central question:
how much value can we expect to get out of compile-time checking?
This is indeed the question. There's both a "theory" and a "practice"
aspect, too.
The type system is going to have three kinds of types:
- types that guarantee identity objects
- types that guarantee value objects
- types that include both kinds of objects
That third kind are a problem: we can specify checks with false
positives (programmer knows the operation is safe, compiler complains
anyway) or false negatives (operation isn't safe, but the compiler
lets it go).
Flowing {Value,Identity}Object property is likely to require shoring up
intersection types too, since we can express Runnable&IdentityObject as
a type bound, but not as a denotable type. Var helps a little here but
ultimately this is a hole through which information will drain.
The arguments you make here are compelling to me, that while it might
work in theory, in practice there are too many holes:
- Legacy code that already deals in Object / interfaces and is not
going to change
- Even in new code, I suspect people will continue to do so, because
as you say, it is tedious for marginal value
- The lack of intersection types will make it worse
- Because of the above, many of the errors would be more like
warnings, making it even weaker
All of this sounds like a recipe for "new complexity that almost no one
will actually use."