changeset 56900:f44032b6dbad records-and-sealed

fixing bug on sealed classes in same compilation unit
author vromero
date Wed, 26 Jun 2019 11:42:07 -0400
parents d4e8276ce5b3
children 74b05fef33c6 88397728dd30
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java test/langtools/tools/javac/sealed/CheckingAttributeAtRuntimeTest.java
diffstat 3 files changed, 85 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jun 24 18:38:44 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jun 26 11:42:07 2019 -0400
@@ -166,7 +166,6 @@
         allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source);
         sourceName = source.name;
         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
-        dontErrorIfSealedExtended = options.isSet("dontErrorIfSealedExtended");
 
         statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
         varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType);
@@ -204,13 +203,6 @@
     boolean useBeforeDeclarationWarning;
 
     /**
-     * Temporary switch, false by default but if set, allows generating classes that can extend a sealed class
-     * even if not listed as a permitted subtype. This allows testing the VM runtime. Should be removed before sealed types
-     * gets integrated
-     */
-    boolean dontErrorIfSealedExtended;
-
-    /**
      * Switch: name of source level; used for error reporting.
      */
     String sourceName;
@@ -4785,45 +4777,6 @@
             chk.validate(tree.implementing, env);
         }
 
-        Type st = types.supertype(c.type);
-        boolean anyParentIsSealed = false;
-        ListBuffer<Pair<ClassType, JCExpression>> potentiallySealedParents = new ListBuffer<>();
-        if (st != Type.noType && (st.tsym.isSealed())) {
-            potentiallySealedParents.add(new Pair<>((ClassType)st, tree.extending));
-            anyParentIsSealed = true;
-        }
-
-        if (tree.implementing != null) {
-            for (JCExpression expr : tree.implementing) {
-                if (expr.type.tsym.isSealed()) {
-                    potentiallySealedParents.add(new Pair<>((ClassType)expr.type, expr));
-                    anyParentIsSealed = true;
-                }
-            }
-        }
-
-        for (Pair<ClassType, JCExpression> sealedParentPair: potentiallySealedParents) {
-            if (!sealedParentPair.fst.permitted.map(t -> t.tsym).contains(c.type.tsym)) {
-                boolean areInSameCompilationUnit = TreeInfo.declarationFor(sealedParentPair.fst.tsym, env.toplevel) != null &&
-                        TreeInfo.declarationFor(tree.sym.outermostClass(), env.toplevel) != null;
-                boolean isSealed = sealedParentPair.fst.tsym.isSealed();
-                if (areInSameCompilationUnit) {
-                    if (sealedParentPair.fst.tsym.isSealed() && !((ClassType)sealedParentPair.fst.tsym.type).isPermittedExplicit) {
-                        sealedParentPair.fst.permitted = sealedParentPair.fst.permitted.prepend(tree.sym.type);
-                    } else if (!dontErrorIfSealedExtended) {
-                        log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
-                    }
-                } else if (!dontErrorIfSealedExtended) {
-                    log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
-                }
-            }
-        }
-
-        if (anyParentIsSealed) {
-            // once we have the non-final keyword this will change
-            c.flags_field |= (c.flags_field & ABSTRACT) != 0 ? SEALED : FINAL;
-        }
-
         c.markAbstractIfNeeded(types);
 
         // If this is a non-abstract class, check that it has no abstract
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Jun 24 18:38:44 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Wed Jun 26 11:42:07 2019 -0400
@@ -143,6 +143,8 @@
         Source source = Source.instance(context);
         allowTypeAnnos = Feature.TYPE_ANNOTATIONS.allowedInSource(source);
         allowDeprecationOnImport = Feature.DEPRECATION_ON_IMPORT.allowedInSource(source);
+        Options options = Options.instance(context);
+        dontErrorIfSealedExtended = options.isSet("dontErrorIfSealedExtended");
     }
 
     /** Switch: support type annotations.
@@ -160,6 +162,13 @@
      */
     boolean completionEnabled = true;
 
+    /**
+     * Temporary switch, false by default but if set, allows generating classes that can extend a sealed class
+     * even if not listed as a permitted subtype. This allows testing the VM runtime. Should be removed before sealed types
+     * gets integrated
+     */
+    boolean dontErrorIfSealedExtended;
+
     /* Verify Imports:
      */
     protected void ensureImportsChecked(List<JCCompilationUnit> trees) {
@@ -1057,6 +1066,45 @@
                 Assert.check(tree.sym.isCompleted());
                 tree.sym.setAnnotationTypeMetadata(new AnnotationTypeMetadata(tree.sym, annotate.annotationTypeSourceCompleter()));
             }
+
+            Type st = types.supertype(tree.sym.type);
+            boolean anyParentIsSealed = false;
+            ListBuffer<Pair<ClassType, JCExpression>> potentiallySealedParents = new ListBuffer<>();
+            if (st != Type.noType && (st.tsym.isSealed())) {
+                potentiallySealedParents.add(new Pair<>((ClassType)st, tree.extending));
+                anyParentIsSealed = true;
+            }
+
+            if (tree.implementing != null) {
+                for (JCExpression expr : tree.implementing) {
+                    if (expr.type.tsym.isSealed()) {
+                        potentiallySealedParents.add(new Pair<>((ClassType)expr.type, expr));
+                        anyParentIsSealed = true;
+                    }
+                }
+            }
+
+            for (Pair<ClassType, JCExpression> sealedParentPair: potentiallySealedParents) {
+                if (!sealedParentPair.fst.permitted.map(t -> t.tsym).contains(tree.sym.type.tsym)) {
+                    boolean areInSameCompilationUnit = TreeInfo.declarationFor(sealedParentPair.fst.tsym, env.toplevel) != null &&
+                            TreeInfo.declarationFor(tree.sym.outermostClass(), env.toplevel) != null;
+                    boolean isSealed = sealedParentPair.fst.tsym.isSealed();
+                    if (areInSameCompilationUnit) {
+                        if (sealedParentPair.fst.tsym.isSealed() && !((ClassType)sealedParentPair.fst.tsym.type).isPermittedExplicit) {
+                            sealedParentPair.fst.permitted = sealedParentPair.fst.permitted.prepend(tree.sym.type);
+                        } else if (!dontErrorIfSealedExtended) {
+                            log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
+                        }
+                    } else if (!dontErrorIfSealedExtended) {
+                        log.error(sealedParentPair.snd, Errors.CantInheritFromSealed(sealedParentPair.fst.tsym));
+                    }
+                }
+            }
+
+            if (anyParentIsSealed) {
+                // once we have the non-final keyword this will change
+                tree.sym.flags_field |= (tree.sym.flags_field & ABSTRACT) != 0 ? SEALED : FINAL;
+            }
         }
 
         /** Add the accessors for fields to the symbol table.
--- a/test/langtools/tools/javac/sealed/CheckingAttributeAtRuntimeTest.java	Mon Jun 24 18:38:44 2019 -0400
+++ b/test/langtools/tools/javac/sealed/CheckingAttributeAtRuntimeTest.java	Wed Jun 26 11:42:07 2019 -0400
@@ -32,23 +32,51 @@
 import com.sun.tools.javac.util.Assert;
 
 public class CheckingAttributeAtRuntimeTest {
-    sealed class Sealed permits Sub {}
 
-    class Sub extends Sealed {}
+    sealed class Sealed1 permits Sub1 {}
 
-    sealed interface SealedI permits Sub2 {}
+    class Sub1 extends Sealed1 {}
 
-    class Sub2 implements SealedI {}
+    sealed interface SealedI1 permits Sub2 {}
+
+    class Sub2 implements SealedI1 {}
+
+    sealed class Sealed2 {}
+
+    class Sub3 extends Sealed2 {}
 
     public static void main(String... args) {
-        Class<?> sealedClass = Sealed.class;
-        Assert.check(sealedClass.isSealed());
-        Assert.check(sealedClass.getPermittedSubtypes().length == 1);
-        Assert.check(sealedClass.getPermittedSubtypes()[0] == Sub.class);
+        Class<?> sealedClass1 = Sealed1.class;
+        Assert.check(sealedClass1.isSealed());
+        Assert.check(sealedClass1.getPermittedSubtypes().length == 1);
+        Assert.check(sealedClass1.getPermittedSubtypes()[0] == Sub1.class);
 
-        Class<?> sealedI = SealedI.class;
+        Class<?> sealedI = SealedI1.class;
         Assert.check(sealedI.isSealed());
         Assert.check(sealedI.getPermittedSubtypes().length == 1);
         Assert.check(sealedI.getPermittedSubtypes()[0] == Sub2.class);
+
+        Class<?> sealedClass2 = Sealed2.class;
+        Assert.check(sealedClass2.isSealed());
+        Assert.check(sealedClass2.getPermittedSubtypes().length == 1);
+        Assert.check(sealedClass2.getPermittedSubtypes()[0] == Sub3.class);
+
+        Class<?> sealedClass3 = Sealed3.class;
+        Assert.check(sealedClass3.isSealed());
+        Assert.check(sealedClass3.getPermittedSubtypes().length == 1);
+        Assert.check(sealedClass3.getPermittedSubtypes()[0] == Sub4.class);
+
+        Class<?> sealedClass4 = Sealed4.class;
+        Assert.check(sealedClass4.isSealed());
+        Assert.check(sealedClass4.getPermittedSubtypes().length == 1);
+        Assert.check(sealedClass4.getPermittedSubtypes()[0] == Sub5.class);
     }
 }
+
+sealed class Sealed3 {}
+
+class Sub4 extends Sealed3 {}
+
+sealed class Sealed4 permits Sub5 {}
+
+class Sub5 extends Sealed4 {}