Relaxed assignment conversions for sealed types

Brian Goetz brian.goetz at
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 

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