Some findings regarding records, sealed types and switch expressions

Daniel Dietrich cafebab3 at googlemail.com
Thu Aug 22 22:54:02 UTC 2019


Thank you, Brian.

I worked on the patterns-deconstruction branch.

I updated to the latest change-set on the records-and-sealed branch and did a re-test of the following findings:


> On 23. Aug 2019, at 00:01, Brian Goetz <brian.goetz at oracle.com> wrote:
> 
>> 1) Questions (sealed)
>> 
>> 1.1) Question: Do make generics in the permits section sense?
>> 
>>   I can’t find a use case. The example below is misleading for a user.
>> 
>>     // why restrict an implementation to specific generic types?
>>     sealed interface A permits B<String> {}
>>     class B<T> implements A
>> 
>>     A a = new B<>(1);
> 
> The permits clause should be a list of _classes_, not of _types_. If the compiler accepts the above, that's a compiler bug.
> 

class Test {
    public static void main(String[] args) {
        A a = new B<>(1);
    }
}

// compiles
sealed interface A permits B<String> {}
record B<T>(T t) implements A {}

>> 1.2) Error: A generic sealed interface cannot be subclassed
>> 
>>     sealed interface A<T> permits B<T> {}
>>     class B<T> implements A<T> {}
>> 
>>     sealed interface A<T> permits B {}
>>     class B<T> implements A<T> {}
>> 
>>     sealed interface A<T> permits B {}
>>     class B implements A {}
>> 
>>    In all three examples we get "cannot inherit from sealed class: A"
> 
> I would expect the latter two sets of examples to work (the last example merely implements the raw type A, rather than the parameterized type A<T>.)  This sounds like a bug.
> 

// error: cannot inherit from sealed class: A1
sealed interface A1<T> permits B1<T> {}
class B1<T> implements A1<T> {}

// error: cannot inherit from sealed class: A2
sealed interface A2<T> permits B2 {}
class B2<T> implements A2<T> {}

// error: cannot inherit from sealed class: A3
sealed interface A3<T> permits B3 {}
class B3 implements A3 {}

>> 2.4) Question: Are instanceof checks planned in switch expressions?
>> 
>>     record A();
>> 
>>     var res = switch(new Object()) {
>>         case A -> 1 // instanceof A check
>>         default -> 0
>>     };
> 
> Yes, eventually, but its not clear whether the binding variable will be required:
> 
>     case A a -> 1
> 
> or whether omitting the binding variable will be OK.  I am worried about ambiguities in `identifier` as a pattern, since it could be a constant pattern or a type pattern.
> 

I see, that makes sense. Scala uses `case _: A => …`.
I don’t know if it would be a good idea to use `_` in Java when the binding variable isn’t needed (currently it fails on patterns-deconstruction).
Having a proper name `case B b -> ...` is straight forward and also the case in lambda expressions for example `(A ignored, B b) -> ...`.

class Test {
    public static void main(String[] args) {
        var res = switch(new Object()) {
            case B _ -> 1;
                  ^--- error: : or -> expected
                   ^-- error: '_' used as an identifier
            default -> -1;
        };
    }
}

class B {}


More information about the amber-dev mailing list