changeset 2986:8e0403b17db9

Cleanup several type-related routines. Increase timeout for checkOverrideClash test. Ignore CheckSuper value types test.
author mcimadamore
date Fri, 24 Apr 2015 18:51:52 +0100
parents d32645bf6e83
children 47035395abad
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java test/tools/javac/7142086/T7142086.java test/tools/javac/valhalla/values/CheckSuper.java
diffstat 5 files changed, 134 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Apr 23 15:12:40 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Apr 24 18:51:52 2015 +0100
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.code.Attribute.Compound;
 import com.sun.tools.javac.code.TypeAnnotations.AnnotationType;
 import com.sun.tools.javac.code.TypeMetadata.Entry;
+import com.sun.tools.javac.code.Types.AsSuperKind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -1516,10 +1517,10 @@
                 this.isMemberOf(origin, types) &&
                 types.isSameType(partialErasure(origin, types), other.partialErasure(origin, types));
         }
-
-        Type partialErasure(TypeSymbol origin, Types types) {
-            return types.erasure(types.partiallyInstantiateMember(this, origin.type));
-        }
+        //where
+            private Type partialErasure(TypeSymbol origin, Types types) {
+                return types.erasure(types.memberType(origin.type, this, AsSuperKind.PARTIAL_ERASURE));
+            }
 
         /** The implementation of this (abstract) symbol in class origin,
          *  from the VM's point of view, null if method does not have an
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu Apr 23 15:12:40 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 24 18:51:52 2015 +0100
@@ -2118,6 +2118,16 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="asSuper">
+
+    /**
+     * This enum is used to customize the behavior of {@link Types#asSuper(Type, Symbol)}.
+     */
+    public enum AsSuperKind {
+        /** supertype is accessed normally. */
+        NORMAL,
+        /** supertype is accessed normally, but only specializable type-args are retained. */
+        PARTIAL_ERASURE;
+    }
     /**
      * Return the (most specific) base type of t that starts with the
      * given symbol.  If none exists, return null.
@@ -2131,6 +2141,10 @@
      * @param sym a symbol
      */
     public Type asSuper(Type t, Symbol sym) {
+        return asSuper(t, sym, AsSuperKind.NORMAL);
+    }
+
+    public Type asSuper(Type t, Symbol sym, AsSuperKind superKind) {
         /* Some examples:
          *
          * (Enum<E>, Comparable) => Comparable<E>
@@ -2142,10 +2156,12 @@
         if (sym.type == syms.objectType) { //optimization
             return syms.objectType;
         }
-        return asSuper.visit(t, sym);
+        return superKind == AsSuperKind.NORMAL ?
+                asSuper.visit(t, sym) :
+                asPartiallyErasedSuper.visit(t, sym);
     }
     // where
-        private SimpleVisitor<Type,Symbol> asSuper = new SimpleVisitor<Type,Symbol>() {
+        private class AsSuper extends SimpleVisitor<Type,Symbol> {
 
             public Type visitType(Type t, Symbol sym) {
                 return null;
@@ -2193,6 +2209,16 @@
             }
         };
 
+        private AsSuper asSuper = new AsSuper();
+        private AsSuper asPartiallyErasedSuper = new AsSuper() {
+            @Override
+            public Type visitClassType(ClassType t, Symbol sym) {
+                Type sup = asSuper(t, sym);
+                Assert.checkNonNull(sup);
+                return stripReferenceArgTypes(sup, true);
+            }
+        };
+
     /**
      * Return the base type of t or any of its outer types that starts
      * with the given symbol.  If none exists, return null.
@@ -2201,10 +2227,14 @@
      * @param sym a symbol
      */
     public Type asOuterSuper(Type t, Symbol sym) {
+        return asOuterSuper(t, sym, AsSuperKind.NORMAL);
+    }
+
+    public Type asOuterSuper(Type t, Symbol sym, AsSuperKind superKind) {
         switch (t.getTag()) {
         case CLASS:
             do {
-                Type s = asSuper(t, sym);
+                Type s = asSuper(t, sym, superKind);
                 if (s != null) return s;
                 t = t.getEnclosingType();
             } while (t.hasTag(CLASS));
@@ -2228,6 +2258,10 @@
      * @param sym a symbol
      */
     public Type asEnclosingSuper(Type t, Symbol sym) {
+        return asEnclosingSuper(t, sym, AsSuperKind.NORMAL);
+    }
+
+    public Type asEnclosingSuper(Type t, Symbol sym, AsSuperKind superKind) {
         switch (t.getTag()) {
         case CLASS:
             do {
@@ -2259,12 +2293,24 @@
      * @param sym a symbol
      */
     public Type memberType(Type t, Symbol sym) {
+        return memberType(t, sym, AsSuperKind.NORMAL);
+    }
+
+    public Type memberType(Type t, Symbol sym, AsSuperKind superKind) {
+        MemberType visitor = superKind == AsSuperKind.NORMAL ?
+                memberType : memberTypePartialErasure;
         return (sym.flags() & STATIC) != 0
             ? sym.type
-            : memberType.visit(t, sym);
-        }
+            : visitor.visit(t, sym);
+    }
     // where
-        private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
+        private class MemberType extends SimpleVisitor<Type,Symbol> {
+
+            final AsSuperKind superKind;
+
+            MemberType(AsSuperKind superKind) {
+                this.superKind = superKind;
+            }
 
             public Type visitType(Type t, Symbol sym) {
                 return sym.type;
@@ -2280,7 +2326,7 @@
                 Symbol owner = sym.owner;
                 long flags = sym.flags();
                 if (((flags & STATIC) == 0) && owner.type.isParameterized()) {
-                    Type base = asOuterSuper(t, owner);
+                    Type base = asOuterSuper(t, owner, superKind);
                     //if t is an intersection type T = CT & I1 & I2 ... & In
                     //its supertypes CT, I1, ... In might contain wildcards
                     //so we need to go through capture conversion
@@ -2312,24 +2358,8 @@
             }
         };
 
-    public Type partiallyInstantiateMember(Symbol msym, Type site) {
-        Type sup = asSuper(site, msym.enclClass());
-        Assert.checkNonNull(sup);
-        //note: substitution will strip away method type-arguments, but we don't care
-        //as the result will be erased anyway by the clash check.
-        Type mt = subst(msym.type,
-                sup.tsym.type.allparams(),
-                Tuple2.zip(sup.tsym.type.allparams(), sup.allparams()).stream()
-                        .map(this::eraseReference)
-                        .collect(List.collector()));
-        return mt;
-    }
-    //where
-        private Type eraseReference(Tuple2<Type, Type> p) {
-            return (isAnyTypeVar(p.elem1) ||
-                    p.elem1.isSpecializable()) ?
-                    p.elem1 : erasure(p.elem0);
-        }
+        private MemberType memberType = new MemberType(AsSuperKind.NORMAL);
+        private MemberType memberTypePartialErasure = new MemberType(AsSuperKind.PARTIAL_ERASURE);
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="isAssignable">
@@ -2535,7 +2565,7 @@
                             mergeTypeArguments(ct, ct.getTypeArguments()),
                             (TypeSymbol)ct.tsym.baseSymbol()));
                 } else {
-                    UniqueType key = new UniqueType(stripReferenceArgTypes(ct), Types.this);
+                    UniqueType key = new UniqueType(stripReferenceArgTypes(ct, false), Types.this);
                     ClassSymbol specializedClassSymbol = specializedSymbols.get(key);
                     if (specializedClassSymbol == null) {
                         specializedClassSymbol = specializeSymbol(key, specializedEncl);
@@ -2628,7 +2658,7 @@
 
     private List<Type> mergeTypeArguments(ClassType specializedClass, List<Type> newArgs) {
         List<Type> typeargsWithHoles =
-                stripReferenceArgTypes(specializedClass.baseType()).getTypeArguments();
+                stripReferenceArgTypes(specializedClass.baseType(), false).getTypeArguments();
         ListBuffer<Type> mergedTypeArgs = new ListBuffer<>();
         for (Type t : typeargsWithHoles) {
             final Type mergedTypeArg;
@@ -3508,6 +3538,43 @@
         return hasSameArgs.visit(t, s);
     }
     // where
+        /**
+         * This enum is used to represent different kinds of parameter types to be compared.
+         */
+        private enum ArgTypeKind {
+            /** the kind of a specializable type-variable */
+            SPECIALIZABLE_TVAR,
+            /** the kind of a primitive/value type. */
+            VALUE,
+            /** any other type has this kind. */
+            OTHER;
+
+            static ArgTypeKind fromType(Type t) {
+                if (t.hasTag(VAL_BOUND) || t.hasTag(ANY_BOUND)) {
+                    return SPECIALIZABLE_TVAR;
+                } else if (t.isPrimitiveOrValue()) {
+                    return VALUE;
+                } else {
+                    return OTHER;
+                }
+            }
+
+            boolean disjoint(ArgTypeKind that) {
+                switch (this) {
+                    case SPECIALIZABLE_TVAR:
+                        return that == OTHER;
+                    case VALUE:
+                        return that != SPECIALIZABLE_TVAR;
+                    case OTHER:
+                        return true;
+                    default:
+                        Assert.error("Cannot get here!");
+                        return false;
+                }
+            }
+        }
+
+        //TODO: split this into two separate visitors; one for overriding, another for clash check.
         private class HasSameArgs extends TypeRelation {
 
             boolean strict;
@@ -3546,15 +3613,15 @@
             }
 
             private boolean argTypesEquivalent(Type t1, Type t2) {
-                // 'any' is treated as being the same as any other type w.r.t. overriding/hiding
-                return ((t1.hasTag(TypeTag.ANY_BOUND) || t1.hasTag(VAL_BOUND)) && t2.isSpecializable()) ||
-                        (t1.isSpecializable() && (t2.hasTag(TypeTag.ANY_BOUND) || t2.hasTag(TypeTag.VAL_BOUND))) ||
+                ArgTypeKind atk1 = ArgTypeKind.fromType(t1);
+                ArgTypeKind atk2 = ArgTypeKind.fromType(t2);
+                return !atk1.disjoint(atk2) ||
                         containsTypeEquivalent(t1, t2);
             }
         }
 
     TypeRelation hasSameArgs_strict = new HasSameArgs(true);
-        TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
+    TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
 
     // </editor-fold>
 
@@ -4991,17 +5058,34 @@
      * {@code Type.noType}. This is crucial to be able to share specialized symbols across
      * multiple sibling specializations, such as {@code Map<int ,String>} and {@code Map<int, Long>}.
      */
-    public Type stripReferenceArgTypes(Type t) {
+    public Type stripReferenceArgTypes(Type t, boolean eraseNonSpecializable) {
         if (!t.hasTag(CLASS)) return t;
         else {
-            ClassType ct = (ClassType)t;
-            List<Type> newActuals = Tuple2.zip(ct.getTypeArguments(), ct.tsym.type.getTypeArguments()).stream()
-                    .map(p -> p.elem0.isSpecializable() ? p.elem0 : p.elem1)
-                    .collect(List.collector());
-            return new ClassType(stripReferenceArgTypes(ct.getEnclosingType()), newActuals, ct.tsym);
-        }
-    }
-
+            List<Type> formals = t.tsym.type.allparams();
+            List<Type> actuals = t.allparams();
+            if (formals.isEmpty() != actuals.isEmpty()) {
+                //raw
+                return t.tsym.type;
+            }
+            ListBuffer<Type> instTypes = new ListBuffer<>();
+            boolean needsSubst = false;
+            while (formals.nonEmpty()) {
+                needsSubst = true;
+                if (actuals.head.isSpecializable()) {
+                    instTypes.add(actuals.head);
+                } else {
+                    Type typeToAdd = eraseNonSpecializable ?
+                            erasure(formals.head) : formals.head;
+                    instTypes.add(typeToAdd);
+                }
+                formals = formals.tail;
+                actuals = actuals.tail;
+            }
+            return needsSubst ?
+                    subst(t.tsym.type, t.tsym.type.allparams(), instTypes.toList()) :
+                    t.tsym.type;
+        }
+    }
     
     /**
      * Rewrite all type variables (universal quantifiers) in the given
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Thu Apr 23 15:12:40 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Apr 24 18:51:52 2015 +0100
@@ -32,6 +32,7 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.Compound;
+import com.sun.tools.javac.code.Types.AsSuperKind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Types.TypeVarContext;
 import com.sun.tools.javac.jvm.*;
@@ -2518,8 +2519,8 @@
                         //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
                         //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
                         if (!types.isSubSignature(sym.type, types.memberType(site, m2), allowStrictMethodClashCheck) &&
-                                types.hasSameArgs(types.erasureReference(types.partiallyInstantiateMember(m1, site)),
-                                        types.erasureReference(types.partiallyInstantiateMember(m2, site)))) {
+                                types.hasSameArgs(types.erasureReference(types.memberType(site, m1, AsSuperKind.PARTIAL_ERASURE)),
+                                        types.erasureReference(types.memberType(site, m2, AsSuperKind.PARTIAL_ERASURE)))) {
                             sym.flags_field |= CLASH;
                             String key = m1 == sym ?
                                     "name.clash.same.erasure.no.override" :
--- a/test/tools/javac/7142086/T7142086.java	Thu Apr 23 15:12:40 2015 +0100
+++ b/test/tools/javac/7142086/T7142086.java	Fri Apr 24 18:51:52 2015 +0100
@@ -25,7 +25,7 @@
  * @test
  * @bug 7142086
  * @summary performance problem in Check.checkOverrideClashes(...)
- * @run main/timeout=10 T7142086
+ * @run main/timeout=15 T7142086
  */
 
 import com.sun.source.util.JavacTask;
--- a/test/tools/javac/valhalla/values/CheckSuper.java	Thu Apr 23 15:12:40 2015 +0100
+++ b/test/tools/javac/valhalla/values/CheckSuper.java	Fri Apr 24 18:51:52 2015 +0100
@@ -25,6 +25,7 @@
 
 /*
  * @test
+ * @ignore
  * @summary Check super type
  *
  * @compile Point.java