changeset 54854:f99466fd6759 sealed

nestmates dont need to add a permits clause
author vromero
date Tue, 12 Feb 2019 18:35:32 -0500
parents 9acdc1ff686a
children fff84ca16810
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java test/langtools/tools/javac/sealed/SealedTest01.out test/langtools/tools/javac/sealed/separate/TestSeparate_Neg.out
diffstat 8 files changed, 42 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Feb 12 18:35:32 2019 -0500
@@ -403,6 +403,10 @@
         return (flags_field & SEALED) != 0;
     }
 
+    public boolean isFinal() {
+        return (flags_field & FINAL) != 0;
+    }
+
     /** Is this symbol declared (directly or indirectly) local
      *  to a method or variable initializer?
      *  Also includes fields of inner classes which are in
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Tue Feb 12 18:35:32 2019 -0500
@@ -977,7 +977,7 @@
             this.allparams_field = null;
             this.supertype_field = null;
             this.interfaces_field = null;
-            this.permitted = null;
+            this.permitted = List.nil();
         }
 
         @Override
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Feb 12 18:35:32 2019 -0500
@@ -878,6 +878,7 @@
      *  @param interfaceExpected true if only an interface is expected here.
      */
     Type attribBase(JCTree tree,
+                    ClassSymbol subType,
                     Env<AttrContext> env,
                     boolean classExpected,
                     boolean interfaceExpected,
@@ -885,9 +886,10 @@
         Type t = tree.type != null ?
             tree.type :
             attribType(tree, env);
-        return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible);
+        return checkBase(t, subType, tree, env, classExpected, interfaceExpected, checkExtensible);
     }
     Type checkBase(Type t,
+                   ClassSymbol subType,
                    JCTree tree,
                    Env<AttrContext> env,
                    boolean classExpected,
@@ -921,8 +923,10 @@
             log.error(pos, Errors.NoIntfExpectedHere);
             return types.createErrorType(t);
         }
+        boolean areNestMembers = subType != syms.unknownSymbol && t.tsym.outermostClass() == subType.outermostClass();
         if (checkExtensible &&
-            ((t.tsym.flags() & FINAL) != 0)) {
+            ((t.tsym.flags() & FINAL) != 0) &&
+            !areNestMembers) {
             log.error(pos,
                       Errors.CantInheritFromFinal(t.tsym));
         }
@@ -4538,7 +4542,7 @@
         Set<Type> boundSet = new HashSet<>();
         if (bounds.nonEmpty()) {
             // accept class or interface or typevar as first bound.
-            bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false);
+            bounds.head.type = checkBase(bounds.head.type, syms.unknownSymbol, bounds.head, env, false, false, false);
             boundSet.add(types.erasure(bounds.head.type));
             if (bounds.head.type.isErroneous()) {
                 return bounds.head.type;
@@ -4554,7 +4558,7 @@
                 // if first bound was a class or interface, accept only interfaces
                 // as further bounds.
                 for (JCExpression bound : bounds.tail) {
-                    bound.type = checkBase(bound.type, bound, env, false, true, false);
+                    bound.type = checkBase(bound.type, syms.unknownSymbol, bound, env, false, true, false);
                     if (bound.type.isErroneous()) {
                         bounds = List.of(bound);
                     }
@@ -4832,26 +4836,29 @@
 
         Type st = types.supertype(c.type);
         boolean anyParentIsSealed = false;
-        ListBuffer<Pair<Type, JCTree>> sealedParents = new ListBuffer<>();
-        if (st != Type.noType && st.tsym.isSealed()) {
-            sealedParents.add(new Pair<>(st, tree.extending));
+        ListBuffer<ClassType> sealedParents = new ListBuffer<>();
+        if (st != Type.noType && (st.tsym.isSealed() || st.tsym.isFinal())) {
+            sealedParents.add((ClassType)st);
             anyParentIsSealed = true;
         }
 
         if (tree.implementing != null) {
             for (JCExpression expr : tree.implementing) {
-                if (expr.type.tsym.isSealed()) {
-                    sealedParents.add(new Pair<>(expr.type, expr));
+                if (expr.type.tsym.isSealed() || expr.type.tsym.isFinal()) {
+                    sealedParents.add((ClassType)expr.type);
                     anyParentIsSealed = true;
                 }
             }
         }
 
-        for (Pair<Type, JCTree> pair: sealedParents) {
-            ClassType parentType = (ClassType)pair.fst;
-            if (!parentType.permitted.map(t -> t.tsym).contains(c.type.tsym)) {
-                if (!dontErrorIfSealedExtended) {
-                    log.error(pair.snd, Errors.CantInheritFromSealed(TreeInfo.symbol(pair.snd)));
+        for (ClassType sealedParent: sealedParents) {
+            if (!sealedParent.permitted.map(t -> t.tsym).contains(c.type.tsym)) {
+                boolean areNestmates = sealedParent.tsym.outermostClass() == tree.sym.outermostClass();
+                boolean isSealed = sealedParent.tsym.isSealed();
+                if (areNestmates && !sealedParent.tsym.isSealed()) {
+                    sealedParent.permitted = sealedParent.permitted.prepend(tree.sym.type);
+                } else if (!dontErrorIfSealedExtended) {
+                    log.error(tree, Errors.CantInheritFromSealed(sealedParent.tsym));
                 }
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Tue Feb 12 18:35:32 2019 -0500
@@ -677,11 +677,11 @@
 
             if (tree.extending != null) {
                 extending = clearTypeParams(tree.extending);
-                supertype = attr.attribBase(extending, baseEnv, true, false, true);
+                supertype = attr.attribBase(extending, sym, baseEnv, true, false, true);
             } else {
                 extending = null;
                 supertype = ((tree.mods.flags & Flags.ENUM) != 0)
-                ? attr.attribBase(enumBase(tree.pos, sym), baseEnv,
+                ? attr.attribBase(enumBase(tree.pos, sym), sym, baseEnv,
                                   true, false, false)
                 : (sym.fullname == names.java_lang_Object)
                 ? Type.noType
@@ -695,7 +695,7 @@
             List<JCExpression> interfaceTrees = tree.implementing;
             for (JCExpression iface : interfaceTrees) {
                 iface = clearTypeParams(iface);
-                Type it = attr.attribBase(iface, baseEnv, false, true, true);
+                Type it = attr.attribBase(iface, sym, baseEnv, false, true, true);
                 if (it.hasTag(CLASS)) {
                     interfaces.append(it);
                     if (all_interfaces != null) all_interfaces.append(it);
@@ -711,7 +711,7 @@
             List<JCExpression> permittedTrees = tree.permitting;
             for (JCExpression permitted : permittedTrees) {
                 permitted = clearTypeParams(permitted);
-                Type pt = attr.attribBase(permitted, baseEnv, false, false, false);
+                Type pt = attr.attribBase(permitted, sym, baseEnv, false, false, false);
                 permittedSubtypes.append(pt);
             }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Tue Feb 12 18:35:32 2019 -0500
@@ -1161,7 +1161,7 @@
      */
     int writePermittedSubtypesIfNeeded(ClassSymbol csym) {
         ClassType ct = (ClassType)csym.type;
-        if (csym.isSealed() && ct.permitted.nonEmpty()) {
+        if (ct.permitted.nonEmpty()) {
             int alenIdx = writeAttr(names.PermittedSubtypes);
             databuf.appendChar(ct.permitted.size());
             for (Type t : ct.permitted) {
@@ -1909,7 +1909,7 @@
             }
         }
 
-        if (c.isSealed() && target.hasSealedTypes()) {
+        if (target.hasSealedTypes()) {
             acount += writePermittedSubtypesIfNeeded(c);
         }
 
--- a/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java	Fri Feb 08 13:56:32 2019 -0500
+++ b/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java	Tue Feb 12 18:35:32 2019 -0500
@@ -225,7 +225,7 @@
                 .getOutputLines(OutputKind.DIRECT);
 
         List<String> expected = List.of(
-                "Test.java:4:24: compiler.err.cant.inherit.from.sealed: Test.Sealed",
+                "Test.java:4:5: compiler.err.cant.inherit.from.sealed: Test.Sealed",
                 "1 error");
         if (!error.containsAll(expected)) {
             throw new AssertionError("Expected output not found. Expected: " + expected);
@@ -264,7 +264,7 @@
                 .getOutputLines(OutputKind.DIRECT);
 
         List<String> expected = List.of(
-                "Sub2.java:3:20: compiler.err.cant.inherit.from.sealed: pkg.Sealed",
+                "Sub2.java:3:1: compiler.err.cant.inherit.from.sealed: pkg.Sealed",
                 "1 error");
         if (!error.containsAll(expected)) {
             throw new AssertionError("Expected output not found. Expected: " + expected);
--- a/test/langtools/tools/javac/sealed/SealedTest01.out	Fri Feb 08 13:56:32 2019 -0500
+++ b/test/langtools/tools/javac/sealed/SealedTest01.out	Tue Feb 12 18:35:32 2019 -0500
@@ -1,5 +1,5 @@
-SealedTest01.java:19:43: compiler.err.cant.inherit.from.sealed: SealedTest01.SC
-SealedTest01.java:20:44: compiler.err.cant.inherit.from.sealed: SealedTest01.SAC
-SealedTest01.java:21:46: compiler.err.cant.inherit.from.sealed: SealedTest01.SI
-SealedTest01.java:22:47: compiler.err.cant.inherit.from.sealed: SealedTest01.SI
+SealedTest01.java:19:12: compiler.err.cant.inherit.from.sealed: SealedTest01.SC
+SealedTest01.java:20:12: compiler.err.cant.inherit.from.sealed: SealedTest01.SAC
+SealedTest01.java:21:12: compiler.err.cant.inherit.from.sealed: SealedTest01.SI
+SealedTest01.java:22:12: compiler.err.cant.inherit.from.sealed: SealedTest01.SI
 4 errors
--- a/test/langtools/tools/javac/sealed/separate/TestSeparate_Neg.out	Fri Feb 08 13:56:32 2019 -0500
+++ b/test/langtools/tools/javac/sealed/separate/TestSeparate_Neg.out	Tue Feb 12 18:35:32 2019 -0500
@@ -1,5 +1,5 @@
-TestSeparate_Neg.java:8:45: compiler.err.cant.inherit.from.sealed: SealedClasses.SC
-TestSeparate_Neg.java:9:46: compiler.err.cant.inherit.from.sealed: SealedClasses.SAC
-TestSeparate_Neg.java:10:48: compiler.err.cant.inherit.from.sealed: SealedClasses.SI
-TestSeparate_Neg.java:11:49: compiler.err.cant.inherit.from.sealed: SealedClasses.SI
+TestSeparate_Neg.java:8:12: compiler.err.cant.inherit.from.sealed: SealedClasses.SC
+TestSeparate_Neg.java:9:12: compiler.err.cant.inherit.from.sealed: SealedClasses.SAC
+TestSeparate_Neg.java:10:12: compiler.err.cant.inherit.from.sealed: SealedClasses.SI
+TestSeparate_Neg.java:11:12: compiler.err.cant.inherit.from.sealed: SealedClasses.SI
 4 errors