Intersection types in patterns

Brian Goetz brian.goetz at oracle.com
Sat Oct 20 16:42:42 UTC 2018


>>     case Point(var x, var y) p: ...
>> 
> 
> Is there a situation where you could have reached that case without
> having a reference to p? If I've understood so far:
> 
>  SomeSuperTypeOfPoint q;
> 
>  switch (q) {
>    case Point(var x, var y) p: ... // p == q and p : Point
>  }

Yes, you could have gotten there via

    switch (getAnObjectForMe()) { 
        case Point(var x, var y) p: 
    }

But, one could always refactor to 

    Object o = getAnObjectForMe();
    switch (o) { 
        case Point(var x, var y) p: 
    }

and we’re back to the previous case.  

> So in the Point case there, you could do something with the fields
> x, y

Careful, binding variables — they may be copied from fields, but we don’t know that.  Deconstruction patterns are really like methods that conditionally return multiple values; but methods don’t have to read fields to return a value.  

> How is the resulting declaration scoped? What if I do...
> 
>  SomeSuperTypeOfPoint q;
> 
>  switch (q) {
>    case Point(var x, var y) p:      ... // p == q and p : Point
>    case OtherPoint(var x, var y) p: ... // p == q and p : OtherPoint
>  }

This is well handled by the flow-scoping rules (and one of the reasons we chose such a scoping).  So the first p is in scope for the statements that follow the first case, and similar for the second.  If you fall through from the first to the second, then there are competing overlapping definitions of `p`, and you get an error.  So scoping is not a reason not to do this (you could have collisions on x and y too, which would be handled by the same set of rules), but I think what you’re getting at here is “I don’t see how its needed, you can always pull the switch target into a variable, and cast it.”  





More information about the amber-spec-experts mailing list