Relaxed assignment conversions for sealed types
Brian Goetz
brian.goetz at oracle.com
Sun Oct 25 17:50:27 UTC 2020
>> But, the part of this that is worth discussing is that yes, this could be a _conversion_
>> rather than assignability. The effect of this would mostly show up in
>> overload selection (where the strongly applicable options are preferred
>> over the loosely ones) and type inference. Its a possibility, but I'm
>> not sure it really buys much, and doesn't really address Tagir's "too
>> magic" concerns. (If anything, conversions are more magic than
>> assignability.)
> I've proposed boxing because i fear that if subtyping and this new conversion are at the same level, we will have trouble with inference because you can go in both direction at the same time.
>
Sure, it's a reasonable thing to consider. But I worry also we're
getting lost in the details of _how_, and the more important
conversation right now is the "what language are we building" one. We
know we have a construct that (a) has the seeds of better type checking
in it, and (b) will tempt people to do things that are not as type safe
as we can make them. I'm skeptical that "do nothing" here is the right
move.
Since I still can't avoid having a paint at the bikeshed, I'll point out
that a sneaky vector by which we could address this is to lean on our
new friend, pattern totality. Suppose we have:
sealed abstract class C permits D { }
final class D extends C { }
We have already said that the type pattern `D d` is total on C (with
some remainder.) We're already considering pattern assignment for total
patterns. For example, if Foo(...) is a deconstruction pattern on Foo,
then the following:
Foo(var x, var y) = aFoo;
would be a valid statement, it would deconstruct the RHS, bind variables
x and y, and throw on the remainder (which in this case includes null.)
Now, note that
D d = c;
could be interpreted as a local variable declaration, _or_ as a pattern
match if the type pattern `D d` is total on C with some remainder. (It
is no accident that a type pattern and a variable declaration look alike.)
Now, one could reasonably object that this might be a clever pun, but
that the users won't get the joke, since it does look so much like an
assignment. In the past, we had toyed with giving this statement some
more obvious syntax, like:
let D d = c;
but over time this felt more and more like a Stroustrup's Rule artifact
(new syntax should LOOK DIFFERENT!) Further, we'd like to have a path
to using patterns in things like method declarations:
void foo(Point(var x, var y) p) { ... x, y, and p are all bound
here... }
which is a pretty natural way to use total patterns (once users are
ready for this, they surely are not now.) Requring that
unconditional-bind be a statement ("let") rather than something more
fluid puts roadblocks to getting there.
So, to summarize, another vector by which we could get there is to say that
D d = c;
is a pattern match of a total pattern (D d) on the operand c. This
would mean we could do this assignment for locals, but wouldn't do
anything for us in method invocation context. That doesn't sound
immediately better, but its a direction to consider.
But, in general: let's try to converge on the goals before we dive too
deep into details.
More information about the amber-spec-experts
mailing list