changeset 2988:58e78a090947

Consolidate specialization-related type routines: * Removed Types.asPartiallyInstantiatedType * Generalized Types.stripReferenceArgTypes into a type mapper accepting customizable type-arg mappings * Restrcutured isReifiable/isSpecializable checks * Restructured hasSameArgs check * Removed Type.isSpecializable (replaced with Type.isPrimitiveOrValue as that has cleaner semantics)
author mcimadamore
date Tue, 28 Apr 2015 12:15:23 +0100
parents 47035395abad
children 1e4495ade29c
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/WhereClause.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java test/tools/javac/valhalla/typespec/AnyReference.out test/tools/javac/valhalla/typespec/TestRefOnly03.out
diffstat 10 files changed, 166 insertions(+), 179 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Apr 28 12:15:23 2015 +0100
@@ -1643,7 +1643,7 @@
                             .allMatch(p -> {
                                 WhereClause.Kind where = whereClauses.get(p.elem1.tsym);
                                 return where == null ||
-                                        where.test(p.elem0);
+                                        where.test(p.elem0, types);
                             }));
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Apr 28 12:15:23 2015 +0100
@@ -153,6 +153,7 @@
      */
     public final Type objectType;
     public final Type objectsType;
+    public final Type valueClassType;
     public final Type classType;
     public final Type classLoaderType;
     public final Type stringType;
@@ -422,6 +423,7 @@
         // Enter predefined classes.
         objectType = enterClass("java.lang.Object");
         objectsType = enterClass("java.util.Objects");
+        valueClassType = enterClass("javax.lang.Value");
         classType = enterClass("java.lang.Class");
         stringType = enterClass("java.lang.String");
         stringBufferType = enterClass("java.lang.StringBuffer");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Tue Apr 28 12:15:23 2015 +0100
@@ -606,10 +606,6 @@
         return tsym != null && (tsym.flags_field & Flags.VALUE) != 0;
     }
 
-    public boolean isSpecializable() {
-        return isPrimitive() || isValue();
-    }
-
     public boolean isInterface() {
         return (tsym.flags() & INTERFACE) != 0;
     }
@@ -1672,11 +1668,6 @@
         public boolean isReference() {
             return types.getTypeVarKind(this) == TypeVarKind.REF;
         }
-
-        @Override
-        public boolean isSpecializable() {
-            return types.getTypeVarKind(this) == TypeVarKind.VAL;
-        }
     }
 
     /** A captured type variable comes from wildcards which can have
@@ -2322,7 +2313,7 @@
         }
 
         @Override
-        public boolean isSpecializable() {
+        public boolean isPrimitiveOrValue() {
             return true;
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Tue Apr 28 12:15:23 2015 +0100
@@ -33,10 +33,11 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
+import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
+import java.util.function.Predicate;
 import java.util.stream.Collector;
 import java.util.function.Function;
-import java.util.function.Predicate;
 
 import javax.tools.JavaFileObject;
 
@@ -291,6 +292,12 @@
         return capture ? capture(site) : site;
     }
 
+    /** Is this type compatible with an 'val' type-variable? */
+    public boolean isValueCompatible(Type t) {
+        return t.isPrimitiveOrValue() ||
+                (t.hasTag(TYPEVAR) && getTypeVarKind((TypeVar)t) == TypeVarKind.VAL);
+    }
+
     /**
      * Is the given type an 'any' type-variable?
      */
@@ -327,7 +334,7 @@
 
             @Override
             public Boolean visitTypeVar(TypeVar t, Void _unused) {
-                return isSpecializable(t);
+                return isSpecializableTypeVar(t);
             }
 
             @Override
@@ -360,16 +367,16 @@
         return isUnbounded.visit(t);
     }
     // where
-        private final ReifiableVisitor isUnbounded = new ReifiableVisitor() {
-            @Override
-            protected boolean isTypeArgumentReifiable(Type actual, TypeVar formal) {
-                return super.isTypeArgumentReifiable(actual, formal) ||
-                        containsType(actual, new WildcardType(syms.objectType,
-                                BoundKind.UNBOUND,
-                                syms.boundClass,
-                                formal));
-            }
-        };
+        private final BaseReifiableVisitor isUnbounded =
+            new BaseReifiableVisitor(this::isTypeArgumentUnbounded);
+
+    public boolean isTypeArgumentUnbounded(Type actual, TypeVar formal) {
+        return isTypeArgumentReifiable(actual) ||
+                    containsType(actual, new WildcardType(syms.objectType,
+                            BoundKind.UNBOUND,
+                            syms.boundClass,
+                            formal));
+    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="asSub">
@@ -451,16 +458,16 @@
             return true;
         }
 
-        boolean tAnyInferenceVar = t.hasTag(UNDETVAR) && isAnyTypeVar(((UndetVar)t).qtype);
-        boolean sAnyInferenceVar = s.hasTag(UNDETVAR) && isAnyTypeVar(((UndetVar)s).qtype);
+        boolean tAnyInferenceVar = t.hasTag(UNDETVAR) && isSpecializableTypeVar(((UndetVar)t).qtype);
+        boolean sAnyInferenceVar = s.hasTag(UNDETVAR) && isSpecializableTypeVar(((UndetVar)s).qtype);
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
 
-        if (tAnyInferenceVar && s.isSpecializable()) {
+        if (tAnyInferenceVar && s.isPrimitiveOrValue()) {
             //special conversion rule from inference var to primitive/value (no boxing)
             ((UndetVar)t).addBound(InferenceBound.UPPER, s, this);
             return true;
-        } else if (sAnyInferenceVar && t.isSpecializable()) {
+        } else if (sAnyInferenceVar && t.isPrimitiveOrValue()) {
             //special conversion rule from primitive/value to inference var (no boxing)
             ((UndetVar)s).addBound(InferenceBound.LOWER, t, this);
             return true;
@@ -975,7 +982,7 @@
     public boolean isSubtype(Type t, Type s, boolean capture) {
         if (t.equalsIgnoreMetadata(s) ||
                 s.hasTag(TypeTag.ANY_BOUND) ||
-                t.isSpecializable() && s.hasTag(VAL_BOUND))
+                (isValueCompatible(t) && s.hasTag(VAL_BOUND)))
             return true;
         if (s.isPartial())
             return isSuperType(s, t);
@@ -1673,7 +1680,7 @@
                 case VOID:
                     return false;
                 case VAL_BOUND:
-                    return s.isSpecializable();
+                    return isValueCompatible(s);
                 case ANY_BOUND:
                     // 'any' to reference cast is always unchecked
                     // Note: 'any' to primitive has already been handled before.
@@ -1992,7 +1999,17 @@
         return isReifiable.visit(t);
     }
     // where
-        static class ReifiableVisitor extends UnaryVisitor<Boolean> {
+        class BaseReifiableVisitor extends UnaryVisitor<Boolean> {
+
+            BiFunction<Type, TypeVar, Boolean> typeArgBiPredicate;
+
+            public BaseReifiableVisitor(BiFunction<Type, TypeVar, Boolean> typeArgBiPredicate) {
+                this.typeArgBiPredicate = typeArgBiPredicate;
+            }
+
+            public BaseReifiableVisitor(Function<Type, Boolean> typeArgPredicate) {
+                this.typeArgBiPredicate = (actual, formal) -> typeArgPredicate.apply(actual);
+            }
 
             public Boolean visitType(Type t, Void ignored) {
                 return true;
@@ -2005,7 +2022,7 @@
                 else {
                     return !t.isParameterized() ||
                             Tuple2.zip(t.allparams(), t.tsym.type.allparams()).stream()
-                                    .allMatch(t2 -> isTypeArgumentReifiable(t2.elem0, (TypeVar)t2.elem1));
+                                    .allMatch(t2 -> typeArgBiPredicate.apply(t2.elem0, (TypeVar)t2.elem1));
                 }
             }
 
@@ -2013,35 +2030,34 @@
             public Boolean visitArrayType(ArrayType t, Void ignored) {
                 return visit(t.elemtype);
             }
-
+        }
+
+        private BaseReifiableVisitor isReifiable = new BaseReifiableVisitor(this::isTypeArgumentReifiable) {
             @Override
             public Boolean visitTypeVar(TypeVar t, Void ignored) {
-                return t.isSpecializable();
-            }
-
-            protected boolean isTypeArgumentReifiable(Type actual, TypeVar formal) {
-                return actual.isSpecializable() || actual.isUnbound();
-            }
-        }
-
-        ReifiableVisitor isReifiable = new ReifiableVisitor();
+                return isValueCompatible(t);
+            }
+        };
 
     public boolean isSpecializable(Type t) {
         return isSpecializable.visit(t);
     }
     // where
-        private UnaryVisitor<Boolean> isSpecializable = new ReifiableVisitor() {
-
+        private BaseReifiableVisitor isSpecializable = new BaseReifiableVisitor(this::isTypeArgumentSpecializable) {
             @Override
             public Boolean visitTypeVar(TypeVar t, Void ignored) {
-                return super.visitTypeVar(t, ignored) || isAnyTypeVar(t);
-            }
-
-            @Override
-            protected boolean isTypeArgumentReifiable(Type actual, TypeVar formal) {
-                return actual.isSpecializable() || isAnyTypeVar(actual);
+                return isSpecializableTypeVar(t);
             }
         };
+
+    public boolean isTypeArgumentReifiable(Type t) {
+        return isValueCompatible(t) || t.isUnbound();
+    }
+
+    public boolean isTypeArgumentSpecializable(Type t) {
+        return (t.hasTag(WILDCARD) && isTypeArgumentSpecializable(((WildcardType)t).type)) ||
+                        t.isPrimitiveOrValue() || isSpecializableTypeVar(t);
+    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Array Utils">
@@ -2215,7 +2231,7 @@
             public Type visitClassType(ClassType t, Symbol sym) {
                 Type sup = asSuper(t, sym);
                 Assert.checkNonNull(sup);
-                return stripReferenceArgTypes(sup, true);
+                return referenceArgTypesAsErasedFormals(sup);
             }
         };
 
@@ -2452,7 +2468,7 @@
                 if (t.isPrimitive()) {
                     return t; /*fast special case*/
                 } else if (t.hasTag(TypeTag.ANY_BOUND) || t.hasTag(TypeTag.VAL_BOUND)) {
-                    return erasureKind.shouldEraseAny() ? syms.objectType : t;
+                    return syms.objectType;
                 } else {
                     //other cases already handled
                     return combineMetadata(t, t);
@@ -2474,8 +2490,12 @@
 
             @Override
             public Type visitTypeVar(TypeVar t, ErasureKind erasureKind) {
-                Type erased = erasure(t.getBound(), erasureKind);
-                return combineMetadata(erased, t);
+                if (isSpecializableTypeVar(t) && !erasureKind.shouldEraseAny()) {
+                    return t;
+                } else {
+                    Type erased = erasure(t.getBound(), erasureKind);
+                    return combineMetadata(erased, t);
+                }
             }
         };
 
@@ -2565,21 +2585,21 @@
                             mergeTypeArguments(ct, ct.getTypeArguments()),
                             (TypeSymbol)ct.tsym.baseSymbol()));
                 } else {
-                    UniqueType key = new UniqueType(stripReferenceArgTypes(ct, false), Types.this);
+                    UniqueType key = new UniqueType(referenceArgTypesAsFormals(ct), Types.this);
                     ClassSymbol specializedClassSymbol = specializedSymbols.get(key);
                     if (specializedClassSymbol == null) {
                         specializedClassSymbol = specializeSymbol(key, specializedEncl);
                     }
                     //return new specialized type
                     List<Type> nonSpecializedTypeArgs = ct.getTypeArguments().stream()
-                            .filter(targ -> !targ.isSpecializable())
+                            .filter(targ -> !targ.isPrimitiveOrValue())
                             .collect(List.collector());
                     return nonSpecializedTypeArgs.isEmpty() ?
                             specializedClassSymbol.type :
                             new ClassType(
                                 specializedEncl,
                                 ct.getTypeArguments().stream()
-                                        .filter(targ -> !targ.isSpecializable()).collect(List.collector()),
+                                        .filter(targ -> !targ.isPrimitiveOrValue()).collect(List.collector()),
                                 specializedClassSymbol) {
                                 @Override
                                 public Type baseType() {
@@ -2658,11 +2678,11 @@
 
     private List<Type> mergeTypeArguments(ClassType specializedClass, List<Type> newArgs) {
         List<Type> typeargsWithHoles =
-                stripReferenceArgTypes(specializedClass.baseType(), false).getTypeArguments();
+                referenceArgTypesAsFormals(specializedClass.baseType()).getTypeArguments();
         ListBuffer<Type> mergedTypeArgs = new ListBuffer<>();
         for (Type t : typeargsWithHoles) {
             final Type mergedTypeArg;
-            if (!t.isSpecializable()) {
+            if (!t.isPrimitiveOrValue()) {
                 mergedTypeArg = newArgs.head;
                 newArgs = newArgs.tail;
             } else {
@@ -2688,7 +2708,7 @@
         //compute name string
         List<String> specNames =
                 Tuple2.zip(List.range(offset, offset + typeargs.length()), typeargs).stream()
-                        .filter(p -> p.elem1.isSpecializable())
+                        .filter(p -> p.elem1.isPrimitiveOrValue())
                         .map(p -> String.join("=", p.elem0.toString(), typeSig(p.elem1)))
                         .collect(List.collector());
 
@@ -2746,7 +2766,7 @@
         Map<Type, Type> tvarsMap = new LinkedHashMap<>();
         List<Type> encl_params = specializedEncl.allparams();
         for (Type t : ct.allparams()) {
-            if (t.isSpecializable()) {
+            if (t.isPrimitiveOrValue()) {
                 continue;
             } else if (t.tsym.owner == ct.tsym) {
                 TypeVariableSymbol tvsym =
@@ -2765,7 +2785,7 @@
 
         //compute actual type-parameters (mix of instantiated types and new tvars)
         List<Type> actuals = Tuple2.zip(ct.tsym.type.allparams(), ct.allparams()).stream()
-                .map(p -> p.elem1.isSpecializable() ? p.elem1 : tvarsMap.get(p.elem0))
+                .map(p -> p.elem1.isPrimitiveOrValue() ? p.elem1 : tvarsMap.get(p.elem0))
                 .collect(List.collector());
 
         //adjust bounds of specialized tvars by replacing old tvars for actuals (see above)
@@ -2813,49 +2833,6 @@
 
         return specializedClassSym;
     }
-
-    /**
-     * Return a type where all non-specializable parameters are replaced with the corresponding
-     * type-parameter erasures. This is useful to compute BytecodeMapping-friendly signatures.
-     */
-    public Type asPartiallyInstantiatedType(Type t) {
-        if (t.hasTag(CLASS)) {
-            List<Type> formals = t.tsym.type.allparams();
-            List<Type> actuals = Tuple2.zip(formals, t.allparams()).stream()
-                    .map(p -> p.elem1.accept(isPartial, null) ? p.elem1 : erasure(p.elem0))
-                    .collect(List.collector());
-            return subst(t.tsym.type, formals, actuals);
-        } else {
-            return t;
-        }
-    }
-    //where
-        UnaryVisitor<Boolean> isPartial = new UnaryVisitor<Boolean>() {
-            @Override
-            public Boolean visitType(Type t, Void _unused) {
-                return t.isSpecializable();
-            }
-
-            @Override
-            public Boolean visitClassType(ClassType t, Void _unused) {
-                return false;
-            }
-
-            @Override
-            public Boolean visitArrayType(ArrayType t, Void _unused) {
-                return false;
-            }
-
-            @Override
-            public Boolean visitWildcardType(WildcardType t, Void _unused) {
-                return t.type.accept(this, null);
-            }
-
-            @Override
-            public Boolean visitTypeVar(TypeVar t, Void aVoid) {
-                return isSpecializableTypeVar(t);
-            }
-        };
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="makeIntersectionType">
@@ -3214,11 +3191,11 @@
      * @return true if t is a sub signature of s.
      */
     public boolean isSubSignature(Type t, Type s) {
-        return isSubSignature(t, s, true);
-    }
-
-    public boolean isSubSignature(Type t, Type s, boolean strict) {
-        return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict);
+        return isSubSignature(t, s, HasSameArgsKind.OVERRIDE);
+    }
+
+    public boolean isSubSignature(Type t, Type s, HasSameArgsKind kind) {
+        return hasSameArgs(t, s, kind) || hasSameArgs(t, erasure(s), kind);
     }
 
     /**
@@ -3527,11 +3504,11 @@
      * where correspondence is by position in the type parameter list.
      */
     public boolean hasSameArgs(Type t, Type s) {
-        return hasSameArgs(t, s, true);
-    }
-
-    public boolean hasSameArgs(Type t, Type s, boolean strict) {
-        return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict);
+        return hasSameArgs(t, s, HasSameArgsKind.OVERRIDE);
+    }
+
+    public boolean hasSameArgs(Type t, Type s, HasSameArgsKind kind) {
+        return hasSameArgs(t, s, kind == HasSameArgsKind.OVERRIDE ? hasSameArgs_strict : hasSameArgs_nonstrict);
     }
 
     private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) {
@@ -3549,8 +3526,8 @@
             /** any other type has this kind. */
             OTHER;
 
-            static ArgTypeKind fromType(Type t) {
-                if (t.hasTag(VAL_BOUND) || t.hasTag(ANY_BOUND)) {
+            static ArgTypeKind fromType(Type t, Types types) {
+                if (types.isSpecializableTypeVar(t)) {
                     return SPECIALIZABLE_TVAR;
                 } else if (t.isPrimitiveOrValue()) {
                     return VALUE;
@@ -3574,13 +3551,18 @@
             }
         }
 
+        public enum HasSameArgsKind {
+            CLASH,
+            OVERRIDE;
+        }
+
         //TODO: split this into two separate visitors; one for overriding, another for clash check.
         private class HasSameArgs extends TypeRelation {
 
-            boolean strict;
-
-            public HasSameArgs(boolean strict) {
-                this.strict = strict;
+            HasSameArgsKind kind;
+
+            public HasSameArgs(HasSameArgsKind kind) {
+                this.kind = kind;
             }
 
             public Boolean visitType(Type t, Type s) {
@@ -3600,7 +3582,7 @@
             @Override
             public Boolean visitForAll(ForAll t, Type s) {
                 if (!s.hasTag(FORALL))
-                    return strict ? false : visitMethodType(t.asMethodType(), s);
+                    return kind == HasSameArgsKind.OVERRIDE ? false : visitMethodType(t.asMethodType(), s);
 
                 ForAll forAll = (ForAll)s;
                 return hasSameBounds(t, forAll)
@@ -3613,15 +3595,15 @@
             }
 
             private boolean argTypesEquivalent(Type t1, Type t2) {
-                ArgTypeKind atk1 = ArgTypeKind.fromType(t1);
-                ArgTypeKind atk2 = ArgTypeKind.fromType(t2);
-                return !atk1.disjoint(atk2) ||
+                ArgTypeKind atk1 = ArgTypeKind.fromType(t1, Types.this);
+                ArgTypeKind atk2 = ArgTypeKind.fromType(t2, Types.this);
+                return (kind == HasSameArgsKind.CLASH && !atk1.disjoint(atk2)) ||
                         containsTypeEquivalent(t1, t2);
             }
         }
 
-    TypeRelation hasSameArgs_strict = new HasSameArgs(true);
-    TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
+    TypeRelation hasSameArgs_strict = new HasSameArgs(HasSameArgsKind.OVERRIDE);
+    TypeRelation hasSameArgs_nonstrict = new HasSameArgs(HasSameArgsKind.CLASH);
 
     // </editor-fold>
 
@@ -5054,39 +5036,50 @@
     // </editor-fold>
 
     /**
-     * Removes reference type-arguments from a parameterized types and replaces them with
-     * {@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>}.
+     * Replaces reference type-arguments from a parameterized types with their formal counterparts.
+     * 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, boolean eraseNonSpecializable) {
-        if (!t.hasTag(CLASS)) return t;
-        else {
+    public Type referenceArgTypesAsFormals(Type t) {
+        return t.map(referenceTargsAsFormals);
+    }
+
+    /**
+     * Replaces reference type-arguments from a parameterized types with the erasure of their formal counterparts.
+     * This is useful in order to compute member clash checks.
+     */
+    public Type referenceArgTypesAsErasedFormals(Type t) {
+        return t.map(referenceTargsAsErasedFormals);
+    }
+
+    class TypeArgMapper extends TypeMapping<Void> {
+
+        Predicate<Type> stripPredicate;
+        BiFunction<Type, Type, Type> optMap;
+
+        TypeArgMapper(Predicate<Type> stripPredicate, BiFunction<Type, Type, Type> optMap) {
+            this.stripPredicate = stripPredicate;
+            this.optMap = optMap;
+        }
+
+        @Override
+        public Type visitClassType(ClassType t, Void aVoid) {
             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;
-        }
-    }
-    
+            List<Type> actuals = t.isRaw() ? formals : t.allparams();
+            List<Type> instTypes = Tuple2.zip(actuals, formals).stream()
+                    .map(p -> stripPredicate.test(p.elem0) ? p.elem0 : optMap.apply(p.elem0, p.elem1))
+                    .collect(List.collector());
+            return subst(t.tsym.type, formals, instTypes);
+        }
+    }
+
+    TypeArgMapper referenceTargsAsFormals =
+            new TypeArgMapper(Type::isPrimitiveOrValue, (actual, formal) -> formal);
+
+    TypeArgMapper referenceTargsAsErasedFormals =
+            new TypeArgMapper(this::isTypeArgumentSpecializable,
+                    (actual, formal) -> erasure(formal));
+
     /**
      * Rewrite all type variables (universal quantifiers) in the given
      * type to wildcards (existential quantifiers).  This is used to
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/WhereClause.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/WhereClause.java	Tue Apr 28 12:15:23 2015 +0100
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.code;
 
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type.TypeVar;
 import com.sun.tools.javac.code.Types.TypeVarKind;
 import com.sun.tools.javac.code.WhereClause.Kind;
 import com.sun.tools.javac.tree.JCTree.JCIdent;
@@ -35,6 +36,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.BiPredicate;
 import java.util.function.Predicate;
 
 /**
@@ -46,19 +48,19 @@
     /**
      * This enum is used to map different kind of receiver type-parameter constraints (aka where clauses).
      */
-    public enum Kind implements Predicate<Type> {
+    public enum Kind implements BiPredicate<Type, Types> {
         /** reference-only tvar */
         REF('L', TypeVarKind.REF) {
             @Override
-            public boolean test(Type type) {
+            public boolean test(Type type, Types types) {
                 return type.isReference();
             }
         },
         /** value-only tvar */
         VAL('Q', TypeVarKind.VAL) {
             @Override
-            public boolean test(Type type) {
-                return type.isSpecializable();
+            public boolean test(Type type, Types types) {
+                return types.isValueCompatible(type);
             }
         };
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Tue Apr 28 12:15:23 2015 +0100
@@ -28,11 +28,11 @@
 import java.util.*;
 
 import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
 
 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.code.Types.HasSameArgsKind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Types.TypeVarContext;
 import com.sun.tools.javac.jvm.*;
@@ -45,8 +45,6 @@
 
 import com.sun.tools.javac.code.Lint;
 import com.sun.tools.javac.code.Lint.LintCategory;
-import com.sun.tools.javac.code.Scope.CompoundScope;
-import com.sun.tools.javac.code.Scope.NamedImportScope;
 import com.sun.tools.javac.code.Scope.WriteableScope;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
@@ -137,7 +135,8 @@
         source = Source.instance(context);
         allowSimplifiedVarargs = source.allowSimplifiedVarargs();
         allowDefaultMethods = source.allowDefaultMethods();
-        allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
+        allowStrictMethodClashCheck = source.allowStrictMethodClashCheck() ?
+                HasSameArgsKind.OVERRIDE : HasSameArgsKind.CLASH;
         allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
         allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
         complexInference = options.isSet("complexinference");
@@ -176,7 +175,7 @@
 
     /** Switch: should unrelated return types trigger a method clash?
      */
-    boolean allowStrictMethodClashCheck;
+    HasSameArgsKind allowStrictMethodClashCheck;
 
     /** Switch: can the @SafeVarargs annotation be applied to private methods?
      */
@@ -1103,7 +1102,7 @@
         boolean checkBound(Type a, Type bound) {
             if (a.isUnbound() || bound.hasTag(TypeTag.ANY_BOUND)) {
                 return true;
-            } else if (a.isSpecializable()) {
+            } else if (a.isPrimitiveOrValue()) {
                 return bound.hasTag(TypeTag.VAL_BOUND);
             } else if (!a.hasTag(WILDCARD)) {
                 a = types.cvarUpperBound(a);
@@ -1426,7 +1425,7 @@
 
                 BoundChecker<JCExpression> bc = new ClassBoundChecker<>(tree.type, args);
                 bc.onFailure((actual, formal, pos) -> {
-                    if (actual.isSpecializable()) {
+                    if (actual.isPrimitiveOrValue() || types.isSpecializableTypeVar(actual)) {
                         checkRefType(pos, actual);
                     } else {
                         log.error(pos, "not.within.bounds", actual, formal);
@@ -2520,7 +2519,7 @@
                         //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.memberType(site, m1, AsSuperKind.PARTIAL_ERASURE)),
-                                        types.erasureReference(types.memberType(site, m2, AsSuperKind.PARTIAL_ERASURE)))) {
+                                        types.erasureReference(types.memberType(site, m2, AsSuperKind.PARTIAL_ERASURE)), HasSameArgsKind.CLASH)) {
                             sym.flags_field |= CLASH;
                             String key = m1 == sym ?
                                     "name.clash.same.erasure.no.override" :
@@ -2560,7 +2559,7 @@
             //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
             //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
             if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
-                if (types.hasSameArgs(types.erasureReference(s.type), types.erasureReference(sym.type))) {
+                if (types.hasSameArgs(types.erasureReference(s.type), types.erasureReference(sym.type), HasSameArgsKind.CLASH)) {
                     log.error(pos,
                             "name.clash.same.erasure.no.hide",
                             sym, sym.location(),
@@ -3523,11 +3522,11 @@
                     sym.name != names.error &&
                     (sym.kind != MTH ||
                      types.hasSameArgs(sym.type, byName.type) ||
-                     types.hasSameArgs(types.erasureReference(sym.type), types.erasureReference(byName.type)))) {
+                     types.hasSameArgs(types.erasureReference(sym.type), types.erasureReference(byName.type), HasSameArgsKind.CLASH))) {
                 if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) {
                     varargsDuplicateError(pos, sym, byName);
                     return true;
-                } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) {
+                } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, HasSameArgsKind.CLASH)) {
                     duplicateErasureError(pos, sym, byName);
                     sym.flags_field |= CLASH;
                     return true;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Tue Apr 28 12:15:23 2015 +0100
@@ -201,9 +201,9 @@
                                                List<JCExpression> args, JCExpression receiverExpr,
                                                List<Type> typeargs, Type receiverType, Type varargsElement) {
         if (typeargs.nonEmpty()) {
-            Predicate<Type> needsIndy = t -> t.isSpecializable() || types.isAnyTypeVar(t);
+            Predicate<Type> needsIndy = t -> t.isPrimitiveOrValue() || types.isSpecializableTypeVar(t);
             if (typeargs.stream().anyMatch(needsIndy)) {
-                receiverType = types.asPartiallyInstantiatedType(receiverType);
+                receiverType = types.referenceArgTypesAsErasedFormals(receiverType);
 
                 List<Object> staticArgs = typeargs.stream()
                         .map(ta -> needsIndy.test(ta) ? types.typeSig(ta).toString() : "")
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Apr 24 18:53:45 2015 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Tue Apr 28 12:15:23 2015 +0100
@@ -292,7 +292,7 @@
                 //member access on arrays never requires specialization!
                 return memberItem;
             }
-            Type memberOwner = types.asPartiallyInstantiatedType(rcvType);
+            Type memberOwner = types.referenceArgTypesAsErasedFormals(rcvType);
             Type memberType = types.memberType(memberOwner, member);
             if (memberType.hasTag(TypeTag.FORALL)) {
                 ForAll fa = (ForAll)memberType;
--- a/test/tools/javac/valhalla/typespec/AnyReference.out	Fri Apr 24 18:53:45 2015 +0100
+++ b/test/tools/javac/valhalla/typespec/AnyReference.out	Tue Apr 28 12:15:23 2015 +0100
@@ -1,5 +1,5 @@
 AnyReference.java:11:21: compiler.err.cant.resolve.location: kindname.variable, f, , , (compiler.misc.location.1: kindname.variable, t, T)
 AnyReference.java:13:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, T)
 AnyReference.java:15:22: compiler.err.type.found.req: int, (compiler.misc.type.req.ref)
-AnyReference.java:17:16: compiler.err.not.within.bounds: T, N
+AnyReference.java:17:16: compiler.err.type.found.req: T, (compiler.misc.type.req.ref)
 4 errors
--- a/test/tools/javac/valhalla/typespec/TestRefOnly03.out	Fri Apr 24 18:53:45 2015 +0100
+++ b/test/tools/javac/valhalla/typespec/TestRefOnly03.out	Tue Apr 28 12:15:23 2015 +0100
@@ -1,4 +1,4 @@
-TestRefOnly03.java:12:46: compiler.err.not.within.bounds: X, Z
-TestRefOnly03.java:12:18: compiler.err.not.within.bounds: X, Z
-TestRefOnly03.java:13:33: compiler.err.not.within.bounds: X, Z
+TestRefOnly03.java:12:46: compiler.err.type.found.req: X, (compiler.misc.type.req.ref)
+TestRefOnly03.java:12:18: compiler.err.type.found.req: X, (compiler.misc.type.req.ref)
+TestRefOnly03.java:13:33: compiler.err.type.found.req: X, (compiler.misc.type.req.ref)
 3 errors