Good catch! I fully support the restriction.

In your other email I guess you are referring to anonymous classes implementing a sealed interface, right? E.g.

sealed interface Foo {
    void m();

    /* static final */ Foo f1 = new Foo() { ... }
    /* static final */ Foo f2 = () -> {};

}

That is, this should be rejected on same ground - given that inference would end up putting mangled type names in the permits clause (well, at least for the anonymous, in the case of the lambda there's not even a name ;-)).

Dunno about the above code - it's not completely unreasonable (it's not hard to imagine a functional interface having some pre-wired default value - e.g. like Predicate::FALSE). Another angle is, instead of banning,these weird subclasses, we just don't add them to the permits clause (*)

(*) there's also a technical reason as to why inferring permitted types based on things inside field initializers and method bodies is not sound: again it has to do with annotation processing. Presumably you want all your inference completed before annotation processors are run. But, by design, annotation processor only requires declarations to be processed, not entire method bodies. So it would not be possible, under the current regime at least, to gather up all permitted types inside all method bodies _before_ annotation processing.

Maurizio

On 09/10/2019 22:26, Brian Goetz wrote:
It is allowable, though somewhat silly, to put the `final` modifier on local classes.

From a hierarchy-protection point of view, allowing local classes to be `sealed` is also silly, as it cannot be extended from outside the method anyway, and even if it could, such types can't show up in APIs that are accessible from outside.

From an exhaustiveness point of view, though, one can imagine having a sealed local hierarchy (sum of records) that will be switched over within the method, though one would have to work pretty hard to imagine that.

Note that a local class cannot be a subtype of a sealed type declared outside the same method (*), since it can't be denoted in the permits clause.

(*) unless the permits clause is inferred.  Yuck.  Now a mangled name would go into the PermittedSubtypes attribute.

Proposal: ban `sealed` and `non-sealed` modifiers on _local_ classes and interfaces.

Reply via email to