Gathering the various threads in this discussion, here’s what seems a sensible 
landing place:

1.  A sealed _class_ with no permitted subtypes is a final class.  The 
distinction between declared-sealed-with-no-permits and declared-final is 
erased away.  [*]

2.  Sealed abstract classes and interfaces with no permitted subtypes are 
illegal. 

3.  If a sealed type does not specify a permits list, it can be inferred by 
enumerating the subtypes in the same compilation unit.  

4.  If a concrete class is a subtype of a sealed type declared in the same 
compilation unit, and none of the modifiers { sealed, non-sealed, final } are 
present, it is inferred to be sealed with an inferred permits list (which, 
according to (1), may be treated as final if there are none.)

5.  (optional) It is an error to specify an explicit permits list if `sealed` 
is not specified.  

6.  Otherwise, a subtype of a sealed type must have exactly one of the 
following modifiers: sealed, non-sealed, final.  

Benefits:
 - No need to support ACC_FINAL in conjunction with ABSTRACT or INTERFACE.  
 - Inference of both sealed and permits clauses are purely local — there is no 
action-at-a-distance (for distances greater than one compilation unit.)  
 - Sealed-ness for subtypes of sealed classes declared separately must be 
explicit.
 - Co-declared hierarchies get significant ceremony reduction.

[*] This forecloses on directly having “dynamic subtypes” of sealed types, in 
the same way we can have dynamic nest mates via Lookup.defineClass(). However, 
there are reasonable workarounds for this should it become desirable.

> On Aug 19, 2019, at 6:58 PM, Brian Goetz <brian.go...@oracle.com> wrote:
> 
> I was suggesting that a class:
> 
>     sealed class X { }
> 
> with no permitted subtypes would be _both_ ACC_FINAL *and* have an empty 
> sealing attribute.  The rationale would be:
> 
>  - Reflects intuition that sealed-with-no-permitted-subtypes really means 
> final, but
>  - Allows reflection to distinguish between the two.
> 
> Maybe the reflection behavior isn't important, at which point we just drop 
> the latter.
> 
> On 8/19/2019 6:52 PM, Alex Buckley wrote:
>> On 8/19/2019 3:22 PM, Brian Goetz wrote:
>>> I don't have a strong opinion on whether "sealed but no permitted subtypes" 
>>> is a habitable space separate from "final", but I'm fine to
>>> say "that means final" for most purposes.  Not sure what reflection
>>> should say; is it OK for a type that is clearly sealed in its declaration 
>>> to report back as "not sealed, but final?"  Or does
>>> that mean it is both sealed _and_ final (an empty PermittedSubtypes 
>>> attribute, plus an ACC_FINAL)?
>> 
>> Are you referring here to a source declaration such as `sealed interface
>> X {}` where, per Vicente, X.class has ACC_FINAL set? I think 
>> X.class.isSealed() should return true and X.class.isFinal() [simplifying for 
>> space] should return false. Has there been any discussion of reclaiming 
>> ACC_SUPER, 0x0020, for ACC_SEALED in v58 class files? Using an empty 
>> attribute to denote sealing is pretty ugly.
>> 
>> Alex
> 

Reply via email to