changeset 3513:9204dd938160

Summary: Erase erasure from the compiler pipeline.
author sadayapalam
date Fri, 26 Aug 2016 16:54:32 +0530
parents 2edcdbb2943a
children a1f724d412b0
files 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/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java test/tools/javac/tree/8067914/E.out test/tools/javac/valhalla/typespec/Augment03.java test/tools/javac/valhalla/typespec/items/m3/tests/TestSyntheticCast.java
diffstat 15 files changed, 186 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Aug 26 16:54:32 2016 +0530
@@ -2428,6 +2428,11 @@
         }
 
         @Override
+        public Type getEnclosingType() {
+            return noType;
+        }
+
+        @Override
         public UnknownType cloneWithMetadata(TypeMetadata md) {
             throw new AssertionError("Cannot add metadata to a 'any' type");
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Aug 26 16:54:32 2016 +0530
@@ -50,6 +50,10 @@
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.comp.Enter;
 import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.tree.JCTree.JCAssign;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.Tuple.Tuple2;
 
@@ -2645,6 +2649,26 @@
         return erasure.visit(ts, ErasureKind.REFERENCE_ONLY);
     }
 
+    // Returns the generic erasure, as opposed to the erasure of a concrete instatiation if possible.
+    // Fixme: Can use a better name ??
+    public Type erasedType(JCExpression expression) {
+        Symbol symbol;
+        switch (expression.getTag()) {
+            case APPLY:
+                symbol = TreeInfo.symbol(((JCMethodInvocation) expression).meth);
+                break;
+            case ASSIGN:
+                symbol = TreeInfo.symbol(((JCAssign) expression).lhs);
+                break;
+            default:
+                symbol = TreeInfo.symbol(expression);
+                break;
+        }
+        return symbol != null ?
+                symbol.kind == MTH ? erasure(((MethodSymbol)symbol).getReturnType()) : symbol.erasure(this) :
+                        erasure(expression.type);
+    }
+
     /**
      * Helper enum that customizes behavior of the main erasure visitor
      */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Aug 26 16:54:32 2016 +0530
@@ -5039,7 +5039,6 @@
             if (that.constructorType == null) {
                 that.constructorType = syms.unknownType;
             }
-            that.unerasedType = syms.unknownType;
             super.visitNewClass(that);
         }
 
@@ -5093,19 +5092,16 @@
         @Override
         public void visitTypeCast(JCTypeCast tree) {
             super.visitTypeCast(tree);
-            tree.unerasedType = syms.unknownType;
         }
 
         @Override
         public void visitTypeTest(JCInstanceOf tree) {
             super.visitTypeTest(tree);
-            tree.unerasedType = syms.unknownType;
         }
 
         @Override
         public void visitNewArray(JCNewArray tree) {
             super.visitNewArray(tree);
-            tree.unerasedType = syms.unknownType;
         }
     }
     // </editor-fold>
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/IndifierTranslator.java	Fri Aug 26 16:54:32 2016 +0530
@@ -113,10 +113,10 @@
             make.at(pos);
             JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
             qualifier.sym = dynSym;
-            qualifier.type = rs.types.erasure(indyType.getReturnType());
+            qualifier.type = indyType;
 
             JCMethodInvocation proxyCall = make.Apply(List.<JCExpression>nil(), qualifier, indyArgs);
-            proxyCall.type = rs.types.erasure(indyType.getReturnType());
+            proxyCall.type = indyType.getReturnType();
             return proxyCall;
         } finally {
             make.at(prevPos);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Aug 26 16:54:32 2016 +0530
@@ -693,7 +693,7 @@
 
     private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
             DiagnosticPosition pos, List<BootstrapArgument<?>> staticArgs, MethodType indyType) {
-        String functionalInterfaceClass = classSig(targetType);
+        String functionalInterfaceClass = classSig(types.erasure(targetType));
         String functionalInterfaceMethodName = samSym.getSimpleName().toString();
         String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
         String implClass = classSig(types.erasure(refSym.owner.type));
@@ -826,7 +826,8 @@
        if (varargsElement != null) {
            Assert.check((meth.flags() & VARARGS) != 0);
        }
-       return transTypes.translateArgs(args, formals, varargsElement, attrEnv);
+       return transTypes.translateArgs(args, formals,
+               varargsElement != null ? types.erasure(varargsElement) : null, attrEnv);
     }
 
     // </editor-fold>
@@ -867,7 +868,6 @@
                 slam.targets = tree.targets;
                 slam.type = tree.type;
                 slam.pos = tree.pos;
-                slam.unerasedType = tree.unerasedType;
                 return slam;
             } finally {
                 make.at(prevPos);
@@ -889,8 +889,8 @@
             switch (tree.kind) {
                 case BOUND:
                     // The receiver is explicit in the method reference
-                    rcvr = addParameter("rec$", types.decorateDescriptor(tree.getQualifierExpression().unerasedType,
-                            tree.getQualifierExpression().type), false);
+                    rcvr = addParameter("rec$", types.decorateDescriptor(tree.getQualifierExpression().type,
+                            types.erasure(tree.getQualifierExpression().type)), false);
                     receiverExpression = attr.makeNullCheck(tree.getQualifierExpression());
                     break;
                 case UNBOUND:
@@ -956,19 +956,19 @@
         private JCExpression makeReceiver(VarSymbol rcvr) {
             if (rcvr == null) return null;
             JCExpression rcvrExpr = make.Ident(rcvr);
-            rcvrExpr.unerasedType = TreeInfo.unerasedTypeOrType(tree.getQualifierExpression());
+            rcvrExpr.type = tree.getQualifierExpression().type;
             Type rcvrType;
             if (tree.sym.enclClass().type == syms.arrayClass.type) {
                 // Map the receiver type to the actually type, not just "array"
-                rcvrType = TreeInfo.unerasedTypeOrType(tree.getQualifierExpression());
+                rcvrType = tree.getQualifierExpression().type;
             } else {
-                rcvrType = types.decorateDescriptor(TreeInfo.unerasedTypeOrType(tree.getQualifierExpression()),
+                rcvrType = types.decorateDescriptor(tree.getQualifierExpression().type,
                          tree.ownerAccessible ? tree.sym.enclClass().type : tree.expr.type);
             }
             if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) {
                 rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType);
-                ((JCExpression)((JCTypeCast)rcvrExpr).clazz).unerasedType = rcvrType;
-                rcvrExpr.unerasedType = rcvrType;
+                ((JCExpression)((JCTypeCast)rcvrExpr).clazz).type = rcvrType;
+                rcvrExpr.type = rcvrType;
             }
             return rcvrExpr;
         }
@@ -985,9 +985,8 @@
 
             //create the qualifier expression
             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
-            select.unerasedType = normalizedUnerasedReferentType;
+            select.type = normalizedUnerasedReferentType;
             select.sym = tree.sym;
-            select.type = tree.sym.erasure(types);
 
             //create the method call expression
             JCExpression apply = make.Apply(List.<JCExpression>nil(), select,
@@ -998,9 +997,11 @@
                     types.erasure(localContext.tree.referentType.getReturnType()));
 
             if (apply.hasTag(TYPECAST)) {
-                ((JCExpression)((JCTypeCast)apply).clazz).unerasedType = normalizedUnerasedReferentType.getReturnType();
+                final JCTypeCast cast = (JCTypeCast) apply;
+                cast.setType(normalizedUnerasedReferentType.getReturnType());
+                cast.clazz.setType(normalizedUnerasedReferentType.getReturnType());
             } else {
-                apply.unerasedType = normalizedUnerasedReferentType.getReturnType();
+                apply.setType(normalizedUnerasedReferentType.getReturnType());
             }
             setVarargsIfNeeded(apply, tree.varargsElement);
             return apply;
@@ -1017,7 +1018,6 @@
                         List.of(make.Ident(params.first())),
                         null);
                 newArr.type = tree.getQualifierExpression().type;
-                newArr.unerasedType = tree.getQualifierExpression().unerasedType;
                 return newArr;
             } else {
                 //create the instance creation expression
@@ -1031,7 +1031,6 @@
                 newClass.constructor = tree.sym;
                 newClass.constructorType = tree.sym.erasure(types);
                 newClass.type = tree.getQualifierExpression().type;
-                newClass.unerasedType = tree.getQualifierExpression().unerasedType;
                 setVarargsIfNeeded(newClass, tree.varargsElement);
                 return newClass;
             }
@@ -1042,8 +1041,7 @@
             vsym.pos = tree.pos;
             params.append(make.VarDef(vsym, null));
             if (genArg) {
-                JCExpression id = make.Ident(vsym).setType(vsym.erasure(types));
-                id.unerasedType = vsym.type;
+                JCExpression id = make.Ident(vsym).setType(vsym.type);
                 args.append(id);
             }
             return vsym;
@@ -1082,7 +1080,7 @@
 
         //finally, compute the type of the indy call
         MethodType indyType = new MethodType(indy_args_types,
-                tree.unerasedType,
+                tree.type,
                 List.<Type>nil(),
                 syms.methodClass);
 
@@ -1192,8 +1190,7 @@
             case NULLCHK:
                 return extractUnerasedType(((JCUnary)expr).arg);
             default:
-                return expr.unerasedType == null ?
-                        expr.type : types.decorateDescriptor(expr.unerasedType, expr.type);
+                return types.decorateDescriptor(expr.type, types.erasure(expr.type));
         }
     }
 
@@ -2128,7 +2125,6 @@
                             if (m.containsKey(lambdaIdent.sym)) {
                                 Symbol tSym = m.get(lambdaIdent.sym);
                                 JCExpression t = make.Ident(tSym).setType(lambdaIdent.type);
-                                t.unerasedType = lambdaIdent.unerasedType;
                                 tSym.setTypeAttributes(lambdaIdent.sym.getRawTypeAttributes());
                                 return t;
                             }
@@ -2140,7 +2136,6 @@
                                 JCExpression t = make.Ident(tSym).setType(lambdaIdent.sym.owner.type);
                                 tSym.setTypeAttributes(lambdaIdent.sym.owner.getRawTypeAttributes());
                                 t = make.Select(t, lambdaIdent.name);
-                                t.unerasedType = lambdaIdent.unerasedType;
                                 t.setType(lambdaIdent.type);
                                 TreeInfo.setSymbol(t, lambdaIdent.sym);
                                 return t;
@@ -2332,7 +2327,7 @@
              * reference mentions type variables in enclosing generic method.
              */
             boolean isAnyfiedReference() {
-                return types.isSpecialized(tree.expr.unerasedType) ||
+                return types.isSpecialized(tree.expr.type) ||
                         types.containsSpecializableTvars(tree.sym.type);
             }
             /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Aug 26 16:54:32 2016 +0530
@@ -1117,7 +1117,7 @@
             !tree.hasTag(SELECT) ||
             TreeInfo.name(((JCFieldAccess) tree).selected) == names._super)
             return false;
-        return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(currentClass, types);
+        return !types.erasure(((JCFieldAccess) tree).selected.type).tsym.isSubClass(currentClass, types);
     }
 
     boolean crossSpecializationBoundaries(Symbol sym, JCTree base) {
@@ -1138,10 +1138,10 @@
         private Type specializedReceiver(Symbol sym, JCTree base) {
             if (base != null && base.hasTag(SELECT)) {
                 //foo.bar - the unerased type of 'foo' is the receiver type
-                return ((JCFieldAccess)base).selected.unerasedType;
+                return ((JCFieldAccess)base).selected.type;
             } else if (base != null && base.hasTag(NEWCLASS)) {
                 //new Baz<...>() - the unerased type of the creatiomn expression is the receiver type
-                return ((JCNewClass)base).unerasedType;
+                return ((JCNewClass)base).type;
             } else {
                 //defaults to symbol owner
                 return sym.owner.type;
@@ -1203,8 +1203,7 @@
             Type unerased = sym.type;
             sym = proxies.findFirst(proxyName(sym.name));
             Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
-            tree = make.at(tree.pos).Ident(sym);
-            tree.unerasedType = unerased;
+            tree = make.at(tree.pos).Ident(sym).setType(unerased);
         }
         JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
         switch (sym.kind) {
@@ -1275,7 +1274,7 @@
                     if (accessor != null) {
                         List<JCExpression> args = List.nil();
                         Type unerasedSite = base != null ?
-                                base.unerasedType :
+                                base.type :
                                 types.asOuterSuper(currentClass.type, accessor.owner);
                         if (!sym.isStatic()) {
                             // Instance access methods get instance
@@ -1287,14 +1286,15 @@
                         }
                         if (base == null) {
                             base = make.QualIdent(accessor.owner);
-                            base.unerasedType = unerasedSite;
+                            if (unerasedSite != null)
+                                base.setType(unerasedSite);
                         }
                         JCExpression receiver = make.Select(base, accessor);
 
-                        JCMethodInvocation app = make.App(receiver, args).setType(accessor.erasure(types).getReturnType());
-                        app.unerasedType = tree.unerasedType != null && tree.unerasedType.hasTag(METHOD) ?
-                                tree.unerasedType.getReturnType() :
-                                tree.unerasedType;
+                        Type applyType = tree.type != null && tree.type.hasTag(METHOD) ?
+                                tree.type.getReturnType() :
+                                tree.type;
+                        JCMethodInvocation app = make.App(receiver, args).setType(applyType);
                         return app;
 
                     // Other accesses to members of outer classes get a
@@ -1302,7 +1302,6 @@
                     } else if (baseReq) {
                         JCExpression sel = make.at(tree.pos).Select(
                             accessBase(tree.pos(), sym), sym).setType(tree.type);
-                        sel.unerasedType = tree.unerasedType;
                         return sel;
                     }
                 }
@@ -1472,14 +1471,12 @@
             ref = make.Ident(sym);
             args = make.Idents(md.params);
         } else {
-            JCExpression site = make.Ident(md.params.head).setType(md.params.head.sym.erasure(types));
-            site.unerasedType = md.params.head.sym.type;
+            JCExpression site = make.Ident(md.params.head).setType(md.params.head.sym.type);
             if (acode % 2 != 0) {
                 //odd access codes represent qualified super accesses - need to
                 //emit reference to the direct superclass, even if the refered
                 //member is from an indirect superclass (JLS 13.1)
-                site.setType(types.erasure(types.supertype(vsym.owner.enclClass().type)));
-                site.unerasedType = types.supertype(vsym.owner.enclClass().type);
+                site.setType(types.supertype(vsym.owner.enclClass().type));
             }
             ref = make.Select(site, sym);
             args = make.Idents(md.params.tail);
@@ -1546,7 +1543,6 @@
         JCIdent callee = make.Ident(names._this);
         callee.sym = constr;
         callee.type = constr.type;
-        callee.unerasedType = constr.type;
         md.body =
             make.Block(0, List.<JCStatement>of(
                 make.Call(
@@ -1968,13 +1964,12 @@
         Symbol lhs = it.next();
         Assert.check(rhs.owner.owner == lhs.owner);
         make.at(pos);
-        JCExpression thiz = make.This(lhs.owner.erasure(types));
-        thiz.unerasedType = lhs.owner.type;
+        JCExpression thiz = make.This(lhs.owner.type);
         return
             make.Exec(
                 make.Assign(
                     make.Select(thiz, lhs),
-                    make.Ident(rhs)).setType(lhs.erasure(types)));
+                    make.Ident(rhs)).setType(lhs.type));
     }
 
     /** Return tree simulating the assignment {@code this.this$n = this$n}.
@@ -1985,13 +1980,12 @@
         VarSymbol lhs = outerThisStack.tail.head;
         Assert.check(rhs.owner.owner == lhs.owner);
         make.at(pos);
-        JCExpression thiz = make.This(lhs.owner.erasure(types));
-        thiz.unerasedType = lhs.owner.type;
+        JCExpression thiz = make.This(lhs.owner.type);
         return
             make.Exec(
                 make.Assign(
                     make.Select(thiz, lhs),
-                    make.Ident(rhs)).setType(lhs.erasure(types)));
+                    make.Ident(rhs)).setType(lhs.type));
     }
 
 /**************************************************************************
@@ -2196,7 +2190,7 @@
      *  @param clazz      The tree identifying type T.
      */
     private JCExpression classOf(JCTree clazz) {
-        return classOfType(clazz.type, TreeInfo.unerasedTypeOrType(clazz), clazz.pos());
+        return classOfType(types.erasure(clazz.type), clazz.type, clazz.pos());
     }
 
     private JCExpression classOfType(Type type, Type unerased, DiagnosticPosition pos) {
@@ -2217,7 +2211,7 @@
                         STATIC | PUBLIC | FINAL, names._class,
                         syms.classType, type.tsym);
                 JCFieldAccess sel = (JCFieldAccess)make_at(pos).Select(make.Type(type), sym);
-                sel.selected.unerasedType = unerased;
+                sel.selected.setType(unerased);
                 return sel;
         default:
             throw new AssertionError();
@@ -2908,9 +2902,9 @@
         }
 
     public void visitTypeCast(JCTypeCast tree) {
-        Type unerasedClazz = TreeInfo.unerasedTypeOrType(tree.clazz);
+        Type unerasedClazz = tree.clazz.type;
         tree.clazz = translate(tree.clazz);
-        ((JCExpression)tree.clazz).unerasedType = unerasedClazz;
+        tree.clazz.setType(unerasedClazz);
         if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
             tree.expr = translate(tree.expr, tree.type);
         else
@@ -2928,7 +2922,8 @@
                 tree.constructor.type.getParameterTypes();
 
         if (isEnum) argTypes = argTypes.prepend(syms.intType).prepend(syms.stringType);
-        tree.args = boxArgs(argTypes, tree.args, tree.varargsElement);
+        tree.args = boxArgs(argTypes, tree.args,
+                tree.varargsElement != null ? types.erasure(tree.varargsElement) : null);
         tree.varargsElement = null;
 
         // If created class is local, add free variables after
@@ -3111,12 +3106,11 @@
 
     public void visitApply(JCMethodInvocation tree) {
         Symbol meth = TreeInfo.symbol(tree.meth);
-        List<Type> argtypes = tree.meth.unerasedType != null ?
-                tree.meth.unerasedType.getParameterTypes() :
-                meth.type.getParameterTypes();
+        List<Type> argtypes = tree.meth.type.getParameterTypes();
         if (meth.name == names.init && meth.owner == syms.enumSym)
             argtypes = argtypes.tail.tail;
-        tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
+        tree.args = boxArgs(argtypes, tree.args,
+                tree.varargsElement != null ? types.erasure(tree.varargsElement) : null);
         tree.varargsElement = null;
         Name methName = TreeInfo.name(tree.meth);
         if (meth.name==names.init) {
@@ -3224,7 +3218,7 @@
     /** Expand a boxing or unboxing conversion if needed. */
     @SuppressWarnings("unchecked") // XXX unchecked
     <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
-        boolean havePrimitive = TreeInfo.unerasedTypeOrType(tree).isPrimitive();
+        boolean havePrimitive = tree.type.isPrimitive();
         if (havePrimitive == type.isPrimitive())
             return tree;
         if (havePrimitive) {
@@ -3232,7 +3226,6 @@
             if (!unboxedTarget.hasTag(NONE)) {
                 if (!types.isSubtype(tree.type, unboxedTarget)) {//e.g. Character c = 89;
                     tree.type = unboxedTarget.constType(tree.type.constValue());
-                    tree.unerasedType = tree.type;
                 }
                 return (T)boxPrimitive(tree, types.erasure(type));
             } else {
@@ -3246,7 +3239,7 @@
 
     /** Box up a single primitive expression. */
     JCExpression boxPrimitive(JCExpression tree) {
-        return boxPrimitive(tree, types.boxedClass(TreeInfo.unerasedTypeOrType(tree)).type);
+        return boxPrimitive(tree, types.boxedClass(tree.type).type);
     }
 
     /** Box up a single primitive expression. */
@@ -3256,7 +3249,7 @@
                                          names.valueOf,
                                          box,
                                          List.<Type>nil()
-                                         .prepend(TreeInfo.unerasedTypeOrType(tree)));
+                                         .prepend(tree.type));
         return make.App(make.QualIdent(valueOfSym), List.of(tree));
     }
 
@@ -3298,7 +3291,7 @@
 
     public void visitAssign(JCAssign tree) {
         tree.lhs = translate(tree.lhs, tree);
-        tree.rhs = translate(tree.rhs, TreeInfo.unerasedTypeOrType(tree.lhs));
+        tree.rhs = translate(tree.rhs, tree.lhs.type);
 
         // If translated left hand side is an Apply, we are
         // seeing an access method invocation. In this case, append
@@ -3500,19 +3493,17 @@
          */
         private void visitArrayForeachLoop(JCEnhancedForLoop tree) {
             make_at(tree.expr.pos());
-            Type erasedExprType = tree.expr.type;
-            Type unerasedExprType = tree.expr.unerasedType;
             VarSymbol arraycache = new VarSymbol(SYNTHETIC,
                                                  names.fromString("arr" + target.syntheticNameChar()),
-                                                 unerasedExprType != null ? unerasedExprType : erasedExprType,
+                                                 tree.expr.type,
                                                  currentMethodSym);
-            JCStatement arraycachedef = make.VarDef(arraycache, tree.expr).setType(erasedExprType);
+            JCStatement arraycachedef = make.VarDef(arraycache, tree.expr).setType(tree.expr.type);
             VarSymbol lencache = new VarSymbol(SYNTHETIC,
                                                names.fromString("len" + target.syntheticNameChar()),
                                                syms.intType,
                                                currentMethodSym);
             JCStatement lencachedef = make.
-                VarDef(lencache, make.Select(make.Ident(arraycache).setType(erasedExprType), syms.lengthVar));
+                VarDef(lencache, make.Select(make.Ident(arraycache).setType(tree.expr.type), syms.lengthVar));
             VarSymbol index = new VarSymbol(SYNTHETIC,
                                             names.fromString("i" + target.syntheticNameChar()),
                                             syms.intType,
@@ -3527,7 +3518,7 @@
             JCExpressionStatement step = make.Exec(makeUnary(PREINC, make.Ident(index)));
 
             Type elemtype = types.elemtype(tree.expr.type);
-            JCExpression loopvarinit = make.Indexed(make.Ident(arraycache).setType(erasedExprType),
+            JCExpression loopvarinit = make.Indexed(make.Ident(arraycache).setType(tree.expr.type),
                                                     make.Ident(index)).setType(elemtype);
             JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods,
                                                   tree.var.name,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java	Fri Aug 26 16:54:32 2016 +0530
@@ -176,7 +176,7 @@
                 TreeInfo.args(tree),
                 null,
                 inferredTypeargs(msym),
-                tree.unerasedType,
+                tree.type,
                 tree.varargsElement);
     }
 
@@ -198,7 +198,7 @@
                     ((JCFieldAccess)tree.meth).selected :
                     makeThis(currentClass.type, currentClass);
             receiverType = tree.meth.hasTag(Tag.SELECT) ?
-                    ((JCFieldAccess)tree.meth).selected.unerasedType : currentClass.type;
+                    ((JCFieldAccess)tree.meth).selected.type : currentClass.type;
         } else {
             receiverExpr = tree.meth.hasTag(Tag.SELECT) ?
                     ((JCFieldAccess)tree.meth).selected :
@@ -329,7 +329,6 @@
                     methInv.meth = make.Select(receiverExpr, TreeInfo.symbol(methInv.meth));
                 }
                 methInv.varargsElement = varargsElement;
-                methInv.unerasedType = tree.type;
 
                 //set type to be inferred type (instead of indy return type). This will cause
                 //usual checkcast to be generated during TransTypes (where required).
@@ -371,14 +370,6 @@
         }
     }
 
-    @Override
-    public <T extends JCTree> T translate(T tree) {
-        if (tree instanceof JCExpression) {
-            ((JCExpression)tree).unerasedType = tree.type;
-        }
-        return super.translate(tree);
-    }
-
     public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
         JCExpression prevEnclOp = this.enclOp;
         this.enclOp = enclOp;
@@ -437,8 +428,6 @@
             result = makeVirtualAccessorCall(tree, List.nil(),
                     (enclOp != null && enclOp.hasTag(ASSIGN)) ? VirtualKind.SETTER : VirtualKind.GETTER);
             return;
-        } else if (tree.name == names._class) {
-            tree.selected.unerasedType = tree.selected.type;
         }
         tree.selected = translate(tree.selected, null);
         result = tree;
@@ -604,7 +593,7 @@
         Symbol meth = TreeInfo.symbol(call.meth);
         if (rs.polymorphicSignatureScope.includes(meth)) {
             //patch unerased type for polysig methods
-            tree.meth.unerasedType = meth.type;
+            tree.meth.type = meth.type;
         }
         if (!(meth instanceof DynamicMethodSymbol) &&
                 call.meth.hasTag(SELECT) &&
@@ -1239,7 +1228,6 @@
                 names.metafactory, static_args, (MethodType)indyType, args.prepend(sel.selected), sel.name, null);
         Type res = vk.asInvType.apply(sel.type);
         methInv.setType(res);
-        methInv.unerasedType = methInv.type;
         return methInv;
     }
 
@@ -1331,7 +1319,6 @@
         JCMethodInvocation methInv = makeIndyCall(sel, currentClass, syms.objectibleDispatch,
                 names.metafactory, List.nil(), (MethodType)indyType, args.prepend(sel.selected), meth.name, meth);
         methInv.setType(mtype.getReturnType());
-        methInv.unerasedType = methInv.type;
         return methInv;
     }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Aug 26 16:54:32 2016 +0530
@@ -29,8 +29,6 @@
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Attribute.TypeCompound;
-import com.sun.tools.javac.code.Type.DelegatedType;
-import com.sun.tools.javac.code.Types.AsSuperKind;
 import com.sun.tools.javac.code.Types.TypeVarContext;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.*;
@@ -45,11 +43,17 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
-import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
 import static com.sun.tools.javac.code.TypeTag.VOID;
-import static com.sun.tools.javac.comp.CompileStates.CompileState;
 
-/** This pass translates Generic Java to conventional Java.
+/** This pass handles certain type translations required to handle Generic Java.
+ *  As of this writing, the two operations performed are
+ *
+ *  (1) Insertion of casts necessitated by type erasure at the class file level.
+ *  (2) Generation of bridge methods required to handle scenarios such as when
+ *      an overriding method differs in signature from the method it overrides.
+ *
+ *  It is noteworthy that this stage of the compiler pipeline does not anymore
+ *  erase the parse trees nor the type decorations on them.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -116,7 +120,7 @@
     JCExpression cast(JCExpression tree, Type target) {
         int oldpos = make.pos;
         make.at(tree.pos);
-        if (!types.isSameType(tree.type, target)) {
+        if (!types.isSameType(types.erasedType(tree), target)) {
             if (!resolve.isAccessible(env, target.tsym))
                 resolve.logAccessErrorInternal(env, tree, target);
             tree = make.TypeCast(make.Type(target), tree).setType(target);
@@ -144,14 +148,14 @@
     JCExpression coerce(JCExpression tree, Type target) {
         Type btarget = target.baseType();
         if (tree.type.isPrimitive() == target.isPrimitive()) {
-            return types.isAssignable(tree.type, btarget, types.noWarnings)
+            return types.isAssignable(types.erasedType(tree), btarget, types.noWarnings)
                 ? tree
                 : cast(tree, btarget);
         }
         return tree;
     }
 
-    /** Given an erased reference type, assume this type as the tree's type.
+    /** Given a reference type, assume this type as the tree's type.
      *  Then, coerce to some given target type unless target type is null.
      *  This operation is used in situations like the following:
      *
@@ -172,26 +176,21 @@
      *  }</pre>
      *
      *  @param tree       The expression tree whose type might need adjustment.
-     *  @param erasedType The expression's type after erasure.
-     *  @param target     The target type, which is usually the erasure of the
-     *                    expression's original type.
+     *  @param type       The expression's type before erasure.
+     *  @param target     The target type
      */
-    JCExpression retype(JCExpression tree, Type erasedType, Type target) {
-//      System.err.println("retype " + tree + " to " + erasedType);//DEBUG
-        if (!erasedType.isPrimitive()) {
+    JCExpression retype(JCExpression tree, Type type, Type target) {
+        if (!type.isPrimitive()) {
             if (target != null && target.isPrimitive()) {
                 target = erasure(tree.type);
             }
-            Type unerasedTarget = target;
-            if (target instanceof ProtoType) {
-                unerasedTarget = ((ProtoType)target).unerasedType;
-                target = ((ProtoType)target).qtype;
-            }
-            tree.type = erasedType;
             if (target != null) {
                 JCExpression coercedExpr = coerce(tree, erasure(target));
-                if (coercedExpr != tree && unerasedTarget != null)
-                    coercedExpr.unerasedType = ((JCExpression)((JCTypeCast)coercedExpr).clazz).unerasedType = unerasedTarget;
+                if (coercedExpr != tree) {
+                    final JCTypeCast cast = (JCTypeCast) coercedExpr;
+                    cast.setType(target);
+                    cast.clazz.setType(target);
+                }
                 return coercedExpr;
             }
         }
@@ -291,11 +290,8 @@
             // The bridge calls this.impl(..), if we have an implementation
             // in the current class, super.impl(...) otherwise.
             JCExpression receiver = (impl.owner == origin)
-                ? make.This(origin.erasure(types))
-                : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
-
-            receiver.unerasedType = (impl.owner == origin) ?
-                    origin.type : types.supertype(origin.type);
+                ? make.This(origin.type)
+                : make.Super(types.supertype(origin.type), origin);
 
             // The type returned from the original method.
             Type calltype = erasure(impl.type.getReturnType());
@@ -306,8 +302,8 @@
                 make.Apply(
                            null,
                            make.Select(receiver, impl).setType(erasure(impl.type)),
-                           translateArgs(make.Idents(md.params), ProtoType.from(origErasure.getParameterTypes(),
-                                   types.decorateDescriptor(types.memberType(origin.type, impl), impl.type).getParameterTypes()), null))
+                           translateArgs(make.Idents(md.params),
+                                   types.decorateDescriptor(types.memberType(origin.type, impl), impl.type).getParameterTypes(), null))
                 .setType(calltype);
             JCStatement stat;
             if (origErasure.getReturnType().hasTag(VOID)) {
@@ -315,7 +311,9 @@
             } else {
                 JCExpression retExpr = coerce(call, types.erasure(bridgeType).getReturnType());
                 if (retExpr.hasTag(Tag.TYPECAST)) {
-                    ((JCTypeCast)retExpr).unerasedType = bridgeType.getReturnType();
+                    final JCTypeCast cast = (JCTypeCast)retExpr;
+                    cast.setType(bridgeType.getReturnType());
+                    cast.clazz.setType(bridgeType.getReturnType());
                 }
                 stat = make.Return(retExpr);
             }
@@ -544,24 +542,23 @@
 
     public void visitMethodDef(JCMethodDecl tree) {
         tree.restype = translate(tree.restype, null);
-        tree.typarams = List.nil();
+        tree.typarams = translate(tree.typarams, null);
         tree.params = translateVarDefs(tree.params);
         tree.recvparam = translate(tree.recvparam, null);
         tree.thrown = translate(tree.thrown, null);
         TypeVarContext typeVarContext = types.withTypeVarContext(tree.sym.whereClauses);
         try {
-            tree.body = translate(tree.body, new ProtoType(tree.sym.erasure(types).getReturnType(), tree.type.getReturnType()));
+            tree.body = translate(tree.body, tree.type.getReturnType());
         } finally {
             typeVarContext.pop();
         }
-        tree.type = erasure(tree.type);
         result = tree;
 
         // Check that we do not introduce a name clash by erasing types.
         for (Symbol sym : tree.sym.owner.members().getSymbolsByName(tree.name)) {
             if (sym != tree.sym &&
                 (sym.flags() & GENERIC_METHOD_BRIDGE) == (tree.sym.flags() & GENERIC_METHOD_BRIDGE) &&
-                types.isSameType(erasure(sym.type), tree.type)) {
+                types.isSameType(erasure(sym.type), erasure(tree.type))) {
                 log.error(tree.pos(),
                           "name.clash.same.erasure", tree.sym,
                           sym);
@@ -573,7 +570,6 @@
     public void visitVarDef(JCVariableDecl tree) {
         tree.vartype = translate(tree.vartype, null);
         tree.init = translate(tree.init, tree.type);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
@@ -610,9 +606,7 @@
 
     public void visitLambda(JCLambda tree) {
         tree.params = translate(tree.params);
-        tree.body = translate(tree.body, tree.body.type==null ?
-                null : new ProtoType(erasure(tree.body.type), tree.body.type));
-        tree.type = erasure(tree.type);
+        tree.body = translate(tree.body, tree.body.type);
         result = tree;
     }
 
@@ -620,7 +614,7 @@
         Type selsuper = types.supertype(tree.selector.type);
         boolean enumSwitch = selsuper != null &&
             selsuper.tsym == syms.enumSym;
-        Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
+        Type target = enumSwitch ? tree.selector.type : syms.intType;
         tree.selector = translate(tree.selector, target);
         tree.cases = translateCases(tree.cases);
         result = tree;
@@ -650,7 +644,6 @@
         tree.cond = translate(tree.cond, syms.booleanType);
         tree.truepart = translate(tree.truepart, tree.type);
         tree.falsepart = translate(tree.falsepart, tree.type);
-        tree.type = erasure(tree.type);
         result = retype(tree, tree.type, pt);
     }
 
@@ -690,52 +683,40 @@
         if (meth instanceof DynamicMethodSymbol) {
             unerasedArgs = meth.type.getParameterTypes();
         }
-        Type mt = meth.erasure(types);
+        Type mt = meth.type;
         boolean useInstantiatedPtArgs =
                 allowGraphInference && !types.isSignaturePolymorphic((MethodSymbol)meth.baseSymbol());
         List<Type> argtypes = useInstantiatedPtArgs ?
-                ProtoType.from(unerasedArgs, unerasedArgs) :
+                unerasedArgs :
                 mt.getParameterTypes();
         if (meth.name == names.init && meth.owner == syms.enumSym)
             argtypes = argtypes.tail.tail;
-        Type unerasedVarargs = tree.varargsElement;
-        if (tree.varargsElement != null)
-            tree.varargsElement = types.erasure(tree.varargsElement);
-        else
-            if (tree.args.length() != argtypes.length()) {
-                log.error(tree.pos(),
-                              "method.invoked.with.incorrect.number.arguments",
-                              tree.args.length(), argtypes.length());
-            }
-        tree.args = translateArgs(tree.args, argtypes, tree.varargsElement != null ?
-                new ProtoType(tree.varargsElement, unerasedVarargs) : null);
+        if (tree.varargsElement == null && tree.args.length() != argtypes.length()) {
+            log.error(tree.pos(),
+                    "method.invoked.with.incorrect.number.arguments",
+                    tree.args.length(), argtypes.length());
+        }
+        tree.args = translateArgs(tree.args, argtypes,
+                tree.varargsElement != null ? types.erasure(tree.varargsElement) : null); // erasure required by API.
 
-        tree.type = types.erasure(tree.type);
         // Insert casts of method invocation results as needed.
         result = retype(tree, mt.getReturnType(), pt);
     }
 
     public void visitNewClass(JCNewClass tree) {
         if (tree.encl != null)
-            tree.encl = translate(tree.encl, erasure(tree.encl.type));
+            tree.encl = translate(tree.encl, tree.encl.type);
 
-        Type erasedConstructorType = tree.constructorType != null ?
-                erasure(tree.constructorType) :
-                null;
+        Type constructorType = tree.constructorType;
 
-        List<Type> argtypes = erasedConstructorType != null && allowGraphInference ?
-                ProtoType.from(erasedConstructorType.getParameterTypes(), tree.constructorType.getParameterTypes()) :
-                tree.constructor.erasure(types).getParameterTypes();
+        List<Type> argtypes = constructorType != null && allowGraphInference ?
+                constructorType.getParameterTypes() :
+                tree.constructor.type.getParameterTypes();
 
         tree.clazz = translate(tree.clazz, null);
-        Type unerasedVarargs = tree.varargsElement;
-        if (tree.varargsElement != null)
-            tree.varargsElement = types.erasure(tree.varargsElement);
-        tree.args = translateArgs(
-            tree.args, argtypes, tree.varargsElement != null ?
-                new ProtoType(tree.varargsElement, unerasedVarargs) : null);
+        tree.args = translateArgs(tree.args, argtypes,
+                tree.varargsElement != null ? types.erasure(tree.varargsElement) : null); // erasure required by API.
         tree.def = translate(tree.def, null);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
@@ -744,7 +725,6 @@
         translate(tree.dims, syms.intType);
         if (tree.type != null) {
             tree.elems = translate(tree.elems, types.elemtype(tree.type));
-            tree.type = erasure(tree.type);
         } else {
             tree.elems = translate(tree.elems, null);
         }
@@ -754,23 +734,20 @@
 
     public void visitParens(JCParens tree) {
         tree.expr = translate(tree.expr, pt);
-        tree.type = erasure(tree.expr.type);
-        tree.unerasedType = tree.expr.unerasedType;
+        tree.type = tree.expr.type;
         result = tree;
     }
 
     public void visitAssign(JCAssign tree) {
-        Type unerasedLhs = tree.lhs.type;
         tree.lhs = translate(tree.lhs, null);
-        tree.rhs = translate(tree.rhs, new ProtoType(tree.lhs.type, unerasedLhs));
-        tree.type = erasure(tree.lhs.type);
+        tree.rhs = translate(tree.rhs, tree.lhs.type);
+        tree.type = tree.lhs.type;
         result = retype(tree, tree.type, pt);
     }
 
     public void visitAssignop(JCAssignOp tree) {
         tree.lhs = translate(tree.lhs, null);
         tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
@@ -797,12 +774,9 @@
     }
 
     public void visitTypeCast(JCTypeCast tree) {
-        Type unerased = TreeInfo.unerasedTypeOrType(tree.clazz);
         tree.clazz = translate(tree.clazz, null);
-        ((JCExpression)tree.clazz).unerasedType = unerased;
         Type originalTarget = tree.type;
-        tree.type = erasure(tree.type);
-        JCExpression newExpression = translate(tree.expr, new ProtoType(tree.type, tree.unerasedType));
+        JCExpression newExpression = translate(tree.expr, tree.type);
         if (newExpression != tree.expr) {
             JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST)
                 ? (JCTypeCast) newExpression
@@ -814,9 +788,8 @@
         if (originalTarget.isIntersection()) {
             Type.IntersectionClassType ict = (Type.IntersectionClassType)originalTarget;
             for (Type c : ict.getExplicitComponents()) {
-                Type ec = erasure(c);
-                if (!types.isSameType(ec, tree.type)) {
-                    tree.expr = coerce(tree.expr, ec);
+                if (!types.isSameType(c, tree.type)) {
+                    tree.expr = coerce(tree.expr, c);
                 }
             }
         }
@@ -844,23 +817,10 @@
     }
 
     public void visitIdent(JCIdent tree) {
-        Type et = tree.sym.erasure(types);
-
-        // Map type variables to their bounds.
-        if (tree.sym.kind == TYP && tree.sym.type.hasTag(TYPEVAR)) {
-            result = make.at(tree.pos).Type(et);
-            ((JCExpression)result).unerasedType = tree.unerasedType;
-        } else
-        // Map constants expressions to themselves.
-        if (tree.type.constValue() != null) {
-            result = tree;
-        }
         // Insert casts of variable uses as needed.
-        else if (tree.sym.kind == VAR) {
-            result = retype(tree, et, pt);
-        }
-        else {
-            tree.type = erasure(tree.type);
+        if (tree.sym.kind == VAR && tree.type.constValue() == null) {
+            result = retype(tree, tree.sym.type, pt);
+        } else {
             result = tree;
         }
     }
@@ -869,60 +829,48 @@
         Type t = types.skipTypeVars(tree.selected.type, false);
         if (t.isCompound()) {
             tree.selected = coerce(
-                translate(tree.selected, tree.selected.type),
-                erasure(tree.sym.owner.type));
+                    translate(tree.selected, tree.selected.type),
+                    tree.sym.owner.type); // FIXME: I<T> should be I<Concrete>
         } else
             tree.selected = translate(tree.selected, t);
 
-        // Map constants expressions to themselves.
-        if (tree.type.constValue() != null) {
-            result = tree;
-        }
         // Insert casts of variable uses as needed.
-        else if (tree.sym.kind == VAR) {
-            result = retype(tree, tree.sym.erasure(types), pt);
-        }
-        else {
-            tree.type = erasure(tree.type);
+        if (tree.sym.kind == VAR && tree.type.constValue() == null) {
+            result = retype(tree, tree.sym.type, pt);
+        } else {
             result = tree;
         }
     }
 
     public void visitReference(JCMemberReference tree) {
         Type t = types.skipTypeVars(tree.expr.type, false);
-        Type receiverTarget = t.isCompound() ? erasure(tree.sym.owner.type) : erasure(t);
-        Type unerasedRecvrType = tree.expr.type;
+        Type receiverTarget = t.isCompound() ? tree.sym.owner.type : t;
+
+        // FIXME: Is there a material loss of information below ??
+
+        // Type unerasedRecvrType = tree.expr.type;
         if (tree.kind == ReferenceKind.UNBOUND) {
             tree.expr = make.Type(receiverTarget);
-            tree.expr.unerasedType = unerasedRecvrType;
+            // tree.expr.unerasedType = unerasedRecvrType;
         } else {
             tree.expr = translate(tree.expr, receiverTarget);
-            tree.expr.unerasedType = unerasedRecvrType;
+            // tree.expr.unerasedType = unerasedRecvrType;
         }
 
-        tree.type = erasure(tree.type);
-        if (tree.varargsElement != null)
-            tree.varargsElement = erasure(tree.varargsElement);
         result = tree;
     }
 
     public void visitTypeArray(JCArrayTypeTree tree) {
-        tree.elemtype = translate(tree.elemtype, null);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
     /** Visitor method for parameterized types.
      */
     public void visitTypeApply(JCTypeApply tree) {
-        JCExpression clazz = translate(tree.clazz, null);
-        clazz.unerasedType = tree.unerasedType;
-        result = clazz.setType(erasure(tree.type));
+        result = tree;
     }
 
     public void visitTypeIntersection(JCTypeIntersection tree) {
-        tree.bounds = translate(tree.bounds, null);
-        tree.type = erasure(tree.type);
         result = tree;
     }
 
@@ -934,46 +882,12 @@
         return types.erasure(t);
     }
 
-    /**
-     * Simple type subclass to model an expected type in the translation subsystem. In certain
-     * cases we need to attach unerased type information on synthetic cast - so translation
-     * should preserve such unerased type info.
-     */
-    static class ProtoType extends DelegatedType {
-
-        Type unerasedType;
-
-        ProtoType(Type qtype, Type unerasedType) {
-            super(qtype.getTag(), qtype);
-            this.unerasedType = unerasedType;
-        }
-
-        @Override
-        public boolean isPrimitive() {
-            return qtype.isPrimitive();
-        }
-
-        @Override
-        public Type cloneWithMetadata(TypeMetadata md) {
-            throw new AssertionError("Not supported");
-        }
-
-        static List<Type> from(List<Type> pts, List<Type> unerasedTypes) {
-            return Tuple2.zip(pts, unerasedTypes).stream()
-                    .map(t -> new ProtoType(t.elem0, t.elem1))
-                    .collect(List.collector());
-        }
-    }
-
 /**************************************************************************
  * main method
  *************************************************************************/
 
     private Env<AttrContext> env;
 
-    private static final String statePreviousToFlowAssertMsg =
-            "The current compile state [%s] of class %s is previous to FLOW";
-
     void translateClass(ClassSymbol c) {
         Env<AttrContext> myEnv = enter.getEnv(c);
         Env<AttrContext> oldEnv = env;
@@ -987,7 +901,7 @@
             pt = null;
             try {
                 JCClassDecl tree = (JCClassDecl) env.tree;
-                tree.typarams = List.nil();
+                tree.typarams = translate(tree.typarams, null);
                 super.visitClassDef(tree);
                 make.at(tree.pos);
                 ListBuffer<JCTree> bridges = new ListBuffer<>();
@@ -995,7 +909,6 @@
                     addBridges(tree.pos(), c, bridges);
                 }
                 tree.defs = bridges.toList().prependList(tree.defs);
-                tree.type = erasure(tree.type);
             } finally {
                 make = savedMake;
                 pt = savedPt;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Aug 26 16:54:32 2016 +0530
@@ -1822,7 +1822,7 @@
             @Override
             public void visitIdent(JCIdent tree) {
                 if (tree.sym.kind == VAR && tree.sym.owner.kind == MTH) {
-                    if (types.requiresThreadLocalBackingBuffer(TreeInfo.unerasedTypeOrType(tree))) {
+                    if (types.requiresThreadLocalBackingBuffer(tree.type)) {
                         if ((tree.sym.flags() & (EFFECTIVELY_FINAL | FINAL | VOLATILE_VALUE)) == 0) {
                             if (!valuesRead.contains(tree.sym)) {
                                 valuesRead = valuesRead.prepend((VarSymbol) tree.sym);
@@ -1840,7 +1840,7 @@
                 if (tree.lhs.hasTag(IDENT)) {
                     JCIdent lhs = (JCIdent) tree.lhs;
                     if (lhs.sym.kind == VAR && lhs.sym.owner.kind == MTH) {
-                        if (types.requiresThreadLocalBackingBuffer(TreeInfo.unerasedTypeOrType(lhs))) {
+                        if (types.requiresThreadLocalBackingBuffer(lhs.type)) {
                             if ((lhs.sym.flags() & (EFFECTIVELY_FINAL | FINAL | VOLATILE_VALUE)) == 0) {
                                 if (!valuesWritten.contains(lhs.sym)) {
                                     valuesWritten = valuesWritten.prepend((VarSymbol) lhs.sym);
@@ -1868,7 +1868,7 @@
                 break;
         }
         Assert.check(code.state.stacksize == 0);
-        genExpr(tree.expr, TreeInfo.unerasedTypeOrType(tree.expr), true).drop();
+        genExpr(tree.expr, tree.expr.type, true).drop();
         Assert.check(code.state.stacksize == 0);
         code.endScopes(limit);
     }
@@ -1992,7 +1992,7 @@
             int startpc = genCrt ? code.curCP() : 0;
             code.statBegin(tree.truepart.pos);
             genExpr(tree.truepart, pt).load();
-            code.state.forceStackTop(TreeInfo.unerasedTypeOrType(tree));
+            code.state.forceStackTop(tree.type);
             if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET,
                                      startpc, code.curCP());
             thenExit = code.branch(goto_);
@@ -2002,7 +2002,7 @@
             int startpc = genCrt ? code.curCP() : 0;
             code.statBegin(tree.falsepart.pos);
             genExpr(tree.falsepart, pt).load();
-            code.state.forceStackTop(TreeInfo.unerasedTypeOrType(tree));
+            code.state.forceStackTop(tree.type);
             if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET,
                                      startpc, code.curCP());
         }
@@ -2055,7 +2055,7 @@
         Assert.check(tree.encl == null && tree.def == null);
         setTypeAnnotationPositions(tree.pos);
 
-        Type newType = TreeInfo.unerasedTypeOrType(tree);
+        Type newType = tree.type;
 
         if (types.isValue(newType)) {
             // For values, the creation sequence is simpler: push all arguments, then emit vnew.
@@ -2106,9 +2106,9 @@
          *  of dimensions.
          */
         Item makeNewArray(JCNewArray tree, int ndims) {
-            Type erasedType = tree.type;
+            Type erasedType = types.erasure(tree.type);
 
-            Type sigType = TreeInfo.unerasedTypeOrType(tree);
+            Type sigType = tree.type;
 
             Type erasedElementType = types.elemtype(erasedType);
             if (types.dimensions(sigType) > ClassFile.MAX_DIMENSIONS) {
@@ -2147,14 +2147,14 @@
     }
 
     public void visitAssign(JCAssign tree) {
-        Item l = genExpr(tree.lhs, TreeInfo.unerasedTypeOrType(tree.lhs));
-        genExpr(tree.rhs, TreeInfo.unerasedTypeOrType(tree.lhs)).load();
+        Item l = genExpr(tree.lhs, tree.lhs.type);
+        genExpr(tree.rhs, tree.lhs.type).load();
         if (tree.rhs.type.hasTag(BOT)) {
             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
                for "regarding a reference as having some other type in a manner that can be proved
                correct at compile time."
             */
-            code.state.forceStackTop(TreeInfo.unerasedTypeOrType(tree.lhs));
+            code.state.forceStackTop(tree.lhs.type);
         }
         result = items.makeAssignItem(l);
     }
@@ -2358,7 +2358,7 @@
         }
 
     public void visitTypeCast(JCTypeCast tree) {
-        Type unerasedType = TreeInfo.unerasedTypeOrType(tree.clazz);
+        Type unerasedType = tree.clazz.type;
         result = wrapIfNeeded(genExpr(tree.expr, tree.clazz.type).load(), unerasedType);
         setTypeAnnotationPositions(tree.pos);
         // Additional code is only needed if we cast to a reference type
@@ -2368,8 +2368,8 @@
         if (types.needsMangling(unerasedType) || //do not skip cast to types containing avars
                 (tree.clazz.type.hasTag(CLASS) && types.isAnyfied(tree.clazz.type.tsym)) || //do not skip cast to raw anyfied
                 (!tree.clazz.type.isPrimitive() &&
-                !types.isSameType(tree.expr.type, tree.clazz.type) &&
-                types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null)) {
+                !types.isSameType(types.erasedType(tree.expr), tree.clazz.type) &&
+                types.asSuper(types.erasedType(tree.expr), tree.clazz.type.tsym) == null)) {
             code.emitop2(checkcast, makeRef(tree.pos(), unerasedType));
         }
     }
@@ -2381,7 +2381,7 @@
     public void visitTypeTest(JCInstanceOf tree) {
         genExpr(tree.expr, tree.expr.type).load();
         setTypeAnnotationPositions(tree.pos);
-        Type unerasedType = TreeInfo.unerasedTypeOrType(tree.clazz);
+        Type unerasedType = tree.clazz.type;
         code.emitop2(instanceof_, makeRef(tree.pos(), unerasedType));
         result = items.makeStackItem(syms.booleanType);
     }
@@ -2437,7 +2437,7 @@
         Symbol sym = tree.sym;
 
         if (tree.name == names._class) {
-            code.emitLdc(makeRef(tree.pos(), TreeInfo.unerasedTypeOrType(tree.selected)));
+            code.emitLdc(makeRef(tree.pos(), tree.selected.type));
             result = items.makeStackItem(pt);
             return;
        }
@@ -2487,7 +2487,7 @@
                 result = items.makeDynamicItem(sym);
                 return;
             } else {
-                sym = Descriptor.of(sym, TreeInfo.unerasedTypeOrType(tree.selected), types);
+                sym = Descriptor.of(sym, tree.selected.type, types);
             }
             if ((sym.flags() & STATIC) != 0) {
                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
@@ -2518,7 +2518,7 @@
 
     public void visitLiteral(JCLiteral tree) {
         if (tree.isDefault()) {
-            emitAndMarkIfNeeded1(tree.unerasedType, types::isSpecializableTypeVar, () -> code.emitop0(aconst_null));
+            emitAndMarkIfNeeded1(tree.type, types::isSpecializableTypeVar, () -> code.emitop0(aconst_null));
             result = items.makeStackItem(tree.type);
         } else if (tree.type.hasTag(BOT)) {
             code.emitop0(aconst_null);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java	Fri Aug 26 16:54:32 2016 +0530
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.jvm.Gen.Descriptor;
 import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeMaker;
 import com.sun.tools.javac.util.*;
@@ -254,7 +255,7 @@
 
         private void appendString(JCTree tree) {
             Type t = tree.type.baseType();
-            Type unerasedType = TreeInfo.unerasedTypeOrType(tree);
+            Type unerasedType = tree.type;
             if (types.isSpecializableTypeVar(unerasedType)) {
                 //this duplicates the logic in SpecializeTypes.makeObjectibleCall to covert anyfied vars into strings
                 MethodType indyType = new MethodType(List.of(unerasedType), syms.stringType, List.nil(), syms.methodClass);
@@ -357,9 +358,9 @@
                 ListBuffer<Type> dynamicArgs = new ListBuffer<>();
                 for (JCTree arg : t) {
                     Object constVal = arg.type.constValue();
-                    Type unerased = TreeInfo.unerasedTypeOrType(arg);
+                    Type unerased = arg.type;
                     Type dynamicArgType = types.isSpecializableTypeVar(unerased) ?
-                            unerased : arg.type;
+                            unerased : types.erasedType((JCExpression) arg);
                     if ("".equals(constVal)) continue;
                     if (arg.type == syms.botType) {
                         dynamicArgs.add(types.boxedClass(syms.voidType).type);
@@ -438,9 +439,9 @@
                     } else {
                         // Ordinary arguments come through the dynamic arguments.
                         recipe.append(TAG_ARG);
-                        Type unerased = TreeInfo.unerasedTypeOrType(arg);
+                        Type unerased = arg.type;
                         Type dynamicArgType = types.isSpecializableTypeVar(unerased) ?
-                                unerased : arg.type;
+                                unerased : types.erasedType((JCExpression) arg);
                         dynamicArgs.add(dynamicArgType);
                         gen.genExpr(arg, dynamicArgType).load();
                     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri Aug 26 16:54:32 2016 +0530
@@ -652,8 +652,6 @@
 
     public static abstract class JCExpression extends JCTree implements ExpressionTree {
 
-        public Type unerasedType;
-
         @Override
         public JCExpression setType(Type type) {
             super.setType(type);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Fri Aug 26 16:54:32 2016 +0530
@@ -209,16 +209,6 @@
         }
     }
 
-    public static Type unerasedTypeOrType(JCTree tree) {
-        if (tree instanceof JCExpression) {
-            JCExpression exp = (JCExpression)tree;
-            return exp.unerasedType != null ? exp.unerasedType : exp.type;
-        } else {
-            //Assert.error("Can't access unerased types on non-expressions!");
-            return null;
-        }
-    }
-
     public static boolean isEnumInit(JCTree tree) {
         switch (tree.getTag()) {
             case VARDEF:
--- a/test/tools/javac/tree/8067914/E.out	Tue Jul 05 15:28:16 2016 +0530
+++ b/test/tools/javac/tree/8067914/E.out	Fri Aug 26 16:54:32 2016 +0530
@@ -1,5 +1,5 @@
 
-class E extends S {
+class E extends S<C> {
     
     E() {
         super();
--- a/test/tools/javac/valhalla/typespec/Augment03.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/test/tools/javac/valhalla/typespec/Augment03.java	Fri Aug 26 16:54:32 2016 +0530
@@ -28,7 +28,6 @@
  * @summary bridge test with fbounds
  * @clean .*
  * @compile Augment03.java
- * @compile Augment03.java
  * @run main Augment03
  */
 public class Augment03 {
--- a/test/tools/javac/valhalla/typespec/items/m3/tests/TestSyntheticCast.java	Tue Jul 05 15:28:16 2016 +0530
+++ b/test/tools/javac/valhalla/typespec/items/m3/tests/TestSyntheticCast.java	Fri Aug 26 16:54:32 2016 +0530
@@ -111,11 +111,10 @@
         K m(Sub<Y, K> s) { return null; }
     }
 
-    @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestSyntheticCast<X/_>;.LTestSyntheticCast$testDoubleCast$2042508302<X/_,Y/_>;.this$0:LTestSyntheticCast<X/_>;")
+    @PoolMapping(opcode = Opcodes.GETFIELD, entry = "LTestSyntheticCast<X/_>;.LTestSyntheticCast$testNoDoubleCast$2042508302<X/_,Y/_>;.this$0:LTestSyntheticCast<X/_>;")
     @PoolMapping(opcode = Opcodes.INVOKEVIRTUAL, entry = "LTestSyntheticCast<X/_>;.id:(Ljava/lang/Object;)Ljava/lang/Object;")
     @PoolMapping(opcode = Opcodes.CHECKCAST, entry = "LTestSyntheticCast$Box<Y/_>;")
-    @PoolMapping(opcode = Opcodes.CHECKCAST, entry = "LTestSyntheticCast$Box<Y/_>;")
-    <any X, any Y> void testDoubleCast(Box<X> b) {
+    <any X, any Y> void testNoDoubleCast(Box<X> b) {
        Box<Y> by = (Box<Y>)id(b);
     }
 }