Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8275497

Compilation error when permits clause references private nested class

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P4
    • tbd
    • 17, 18
    • tools

    Description

      The following compiles in jshell:

      jshell> public abstract sealed class Test permits Test.NoInstance {
         ...> private final class NoInstance extends Test {}
         ...> }
      | replaced class Test

      But not in javac:

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ cat Test.java
      public abstract sealed class Test permits Test.NoInstance {
          private final class NoInstance extends Test {}
      }

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ javac Test.java
      Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
      Test.java:1: error: Test.NoInstance has private access in Test
      public abstract sealed class Test permits Test.NoInstance {
                                                    ^
      Test.java:2: error: class is not allowed to extend sealed class: Test (as it is not listed in its permits clause)
          private final class NoInstance extends Test {}

      The JLS states:
      https://docs.oracle.com/javase/specs/jls/se17/html/jls-8.html#jls-8.1.6

      > Every TypeName must name an accessible class (§6.6), or a compile-time error occurs.

      I'd say javac is right and jshell should reject this class, according to
      https://docs.oracle.com/javase/specs/jls/se17/html/jls-6.html#jls-6.6.1

      > Otherwise, the member or constructor is declared private. Access is permitted only when the access occurs from within the body of the top level class or interface that encloses the declaration of the member or constructor.

      Since the permits clause is not part of the body of the top level class, though 1) I find this restriction unnecessary, intuitively, and 2) if we nest everything 1 level, then this works again in javac, so the behaviour isn't regular:

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ cat Test.java
      public class Test {
          public static abstract sealed class X permits X.NoInstance {
              private final class NoInstance extends X {}
          }
      }

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ javac Test.java

      Also, if we remove the permits clause and let the compiler infer it, then it works again:

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ cat Test.java
      public abstract sealed class Test {
          private final class NoInstance extends Test {}
      }

      lukas@DESKTOP-F2SE3C1 MINGW64 ~
      $ javac Test.java

      So, I'm not really sure who's right here, but there do seem to be some inconsistencies that seem to be worth sorting out.

      Attachments

        Activity

          People

            jlahoda Jan Lahoda
            leder Lukas Eder
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated: