changeset 3281:dddf65a2e118

Fix: do not generate desugared generic method class for abstract methods Fix: deal with 'this'/'super' references from desugared class
author mcimadamore
date Tue, 22 Dec 2015 19:11:56 +0000
parents 2bb582ce72c4
children 3ae1321e6516
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java
diffstat 1 files changed, 49 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Tue Dec 22 14:59:35 2015 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Tue Dec 22 19:11:56 2015 +0000
@@ -26,7 +26,6 @@
 package com.sun.tools.javac.comp;
 
 import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Flags.Flag;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
@@ -34,7 +33,6 @@
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument;
 import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol.BootstrapArgument.Kind;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.TypeSymbol;
 import com.sun.tools.javac.code.Symbol.TypeVariableSymbol;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
@@ -74,6 +72,7 @@
 import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeScanner;
+import com.sun.tools.javac.tree.TreeTranslator;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Filter;
@@ -124,6 +123,7 @@
 
     private Types types;
     private Enter enter;
+    private Check chk;
     private CompileStates compileStates;
     private Log log;
 
@@ -134,6 +134,7 @@
         context.put(specializeTypesKey, this);
         types = Types.instance(context);
         enter = Enter.instance(context);
+        chk = Check.instance(context);
         compileStates = CompileStates.instance(context);
         log = Log.instance(context);
         Options options = Options.instance(context);
@@ -422,7 +423,7 @@
 
     @Override
     public void visitMethodDef(JCMethodDecl tree) {
-        if (desugarGenericMethods && tree.typarams != null &&
+        if (desugarGenericMethods && (tree.sym.flags() & Flags.ABSTRACT) == 0 && tree.typarams != null &&
                 tree.typarams.stream().anyMatch(p -> types.isAnyTypeVar(p.type))) {
             //desugar specializable method to inner classes (only static for now)
             tree = makeGenericMethodClass(tree);
@@ -596,6 +597,7 @@
      */
     private JCMethodInvocation rewriteSuperCallIfNeeded(JCMethodInvocation tree) {
         if (currentMethod != null &&
+                !desugarGenericMethods &&
                 currentMethod.type.hasTag(TypeTag.FORALL) &&
                 ((ForAll)currentMethod.type).tvars.stream().anyMatch(types::isAnyTypeVar) &&
                 tree.meth.hasTag(Tag.SELECT) &&
@@ -821,7 +823,7 @@
         genMethodClassSym.members().enter(desugaredMethod);
 
         JCMethodDecl desugaredMethodDecl = make.MethodDef(desugaredMethod, tree.body);
-        new GenericMethodPatcher(tree, desugaredMethodDecl, oldTypeParams, newTypeParams).scan(desugaredMethodDecl);
+        desugaredMethodDecl = new GenericMethodPatcher(tree, desugaredMethodDecl, oldTypeParams, newTypeParams).translate(desugaredMethodDecl);
 
         //create a default constructor for the inner class
         MethodSymbol defaultConstr = new MethodSymbol(Flags.PUBLIC, names.init,
@@ -874,9 +876,10 @@
         return bridgeDecl;
     }
     //where
-        class GenericMethodPatcher extends TreeScanner {
+        class GenericMethodPatcher extends TreeTranslator {
             Map<Symbol, Symbol> paramMap;
             List<Type> oldTypeVars, newTypeVars;
+            Symbol oldMeth, newMeth;
 
             GenericMethodPatcher(JCMethodDecl oldMeth, JCMethodDecl newMeth,
                                  List<Type> oldTypeVars, List<Type> newTypeVars) {
@@ -884,48 +887,77 @@
                         .collect(Collectors.toMap(p -> p.elem0.sym, p -> p.elem1.sym));
                 this.oldTypeVars = oldTypeVars;
                 this.newTypeVars = newTypeVars;
+                this.oldMeth = oldMeth.sym;
+                this.newMeth = newMeth.sym;
             }
 
             @Override
-            public void scan(JCTree tree) {
-                super.scan(tree);
-                if (tree != null && tree.type != null) {
-                    tree.type = patchTypeVars(tree.type);
+            @SuppressWarnings("unchecked")
+            public <T extends JCTree> T translate(T tree) {
+                JCTree newTree = super.translate(tree);
+                if (newTree != null && newTree.type != null) {
+                    newTree.type = patchTypeVars(newTree.type);
                 }
+                return (T)newTree;
             }
 
             @Override
             public void visitNewClass(JCNewClass tree) {
                 super.visitNewClass(tree);
-                tree.constructorType = patchTypeVars(tree.constructorType);
+                JCNewClass newTree = (JCNewClass)result;
+                newTree.constructorType = patchTypeVars(newTree.constructorType);
             }
 
             @Override
             public void visitLambda(JCLambda tree) {
                 super.visitLambda(tree);
-                tree.targets = tree.targets.stream()
+                JCLambda newTree = (JCLambda)result;
+                newTree.targets = newTree.targets.stream()
                         .map(this::patchTypeVars).collect(List.collector());
             }
 
             @Override
             public void visitReference(JCMemberReference tree) {
                 super.visitReference(tree);
-                tree.targets = tree.targets.stream()
+                JCMemberReference newTree = (JCMemberReference)result;
+                newTree.targets = newTree.targets.stream()
                         .map(this::patchTypeVars).collect(List.collector());
-                tree.referentSite = patchTypeVars(tree.referentSite);
-                tree.referentType = patchTypeVars(tree.referentType);
+                newTree.referentSite = patchTypeVars(newTree.referentSite);
+                newTree.referentType = patchTypeVars(newTree.referentType);
             }
 
             @Override
             public void visitIdent(JCIdent tree) {
-                super.visitIdent(tree);
-                tree.sym = patchParam(tree.sym);
+                if ((tree.name.equals(names._this) || tree.name.equals(names._super)) &&
+                        currentClass.isSubClass(tree.type.tsym, types)) {
+                    JCIdent typ = make.Ident(currentClass.name);
+                    typ.sym = currentClass;
+                    typ.type = currentClass.type;
+                    JCFieldAccess sel = make.Select(typ, tree.name);
+                    sel.sym = tree.sym;
+                    sel.type = tree.type;
+                    result = sel;
+                } else {
+                    tree.sym = patchParam(tree.sym);
+                    result = tree;
+                }
+            }
+
+            @Override
+            public void visitClassDef(JCClassDecl tree) {
+                super.visitClassDef(tree);
+                JCClassDecl newTree = (JCClassDecl)result;
+                if (newTree.sym.owner == oldMeth) {
+                    newTree.sym.owner = newMeth;
+                    newTree.sym.flatname = chk.localClassName(newTree.sym);
+                }
             }
 
             @Override
             public void visitSelect(JCFieldAccess tree) {
                 super.visitSelect(tree);
-                tree.sym = patchParam(tree.sym);
+                JCFieldAccess newTree = (JCFieldAccess)result;
+                newTree.sym = patchParam(newTree.sym);
             }
 
             Type patchTypeVars(Type t) {