changeset 1150:cf1816277dd1

Miscellaneous improvements *) Moved Unlambda after type erasure *) Refined implementation of Types.findDescriptor to match latest spec draft
author mcimadamore
date Thu, 03 Nov 2011 19:37:56 +0000
parents 3721384cb546
children 3b32a4a431f7
files src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java src/share/classes/com/sun/tools/javac/comp/TransTypes.java src/share/classes/com/sun/tools/javac/main/JavaCompiler.java test/tools/javac/lambda/sqe/SAM_types/Helper.java
diffstat 7 files changed, 206 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Nov 03 19:37:56 2011 +0000
@@ -495,34 +495,9 @@
          * substitutable with each method in the original list.
          */
         private MethodType mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
-            //merge return types - this is done in two phases: (i) first, the most
-            //specific return type using return type substitutability (as defined in JLS 8.4.5);
-            //(ii) if this fails, a second attempt is made using unchecked subtyping
-            boolean phase2 = false;
-            Type restype = null;
-            while (restype == null) {
-                outer: for (Symbol msym1 : methodSyms) {
-                    Type mt1 = memberType(origin.type, msym1);
-                    for (Symbol msym2 : methodSyms) {
-                        Type mt2 = memberType(origin.type, msym2);
-                        if (phase2 ?
-                                !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType()) :
-                                !returnTypeSubstitutable(mt1, mt2)) {
-                            continue outer;
-                        }
-                    }
-                    restype = mt1.getReturnType();
-                }
-                if (phase2) {
-                    break;
-                } else {
-                    phase2 = true;
-                }
-            }
-            if (restype == null) return null;
             //merge argument types - simply take the signature that is a
             //subsigature of all other signatures in the list (as per JLS 8.4.2)
-            List<Type> argtypes = null;
+            List<Symbol> mostSpecific = List.nil();
             outer: for (Symbol msym1 : methodSyms) {
                 Type mt1 = memberType(origin.type, msym1);
                 for (Symbol msym2 : methodSyms) {
@@ -531,12 +506,39 @@
                         continue outer;
                     }
                 }
-                argtypes = mt1.getParameterTypes();
-                break;
+                mostSpecific = mostSpecific.prepend(msym1);
             }
-            if (argtypes == null) {
-                argtypes = erasure(memberType(origin.type, methodSyms.head)).getParameterTypes();
+            if (mostSpecific.isEmpty()) {
+                return null;//argtypes = erasure(memberType(origin.type, methodSyms.head)).getParameterTypes();
             }
+            
+              
+            //merge return types - this is done in two phases: (i) first, the most
+            //specific return type using return type substitutability (as defined in JLS 8.4.5);
+            //(ii) if this fails, a second attempt is made using unchecked subtyping
+            boolean phase2 = false;
+            Symbol bestSoFar = null;
+            while (bestSoFar == null) {
+                outer: for (Symbol msym1 : mostSpecific) {
+                    Type mt1 = memberType(origin.type, msym1);
+                    for (Symbol msym2 : methodSyms) {
+                        Type mt2 = memberType(origin.type, msym2);
+                        if (phase2 ?
+                                !returnTypeSubstitutable(mt1, mt2) : 
+                                !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
+                            continue outer;
+                        }
+                    }
+                    bestSoFar = msym1;
+                }
+                if (phase2) {
+                    break;
+                } else {
+                    phase2 = true;
+                }
+            }
+            if (bestSoFar == null) return null;
+            
             //merge thrown types - form the union of all the thrown types in
             //all the signatures in the list
             List<Type> thrown = null;
@@ -546,13 +548,15 @@
                     mt1.getThrownTypes() :
                     chk.intersect(mt1.getThrownTypes(), thrown);
             }
-            return new MethodType(argtypes, restype, thrown, syms.methodClass);
+            
+            Type mt = memberType(origin.type, bestSoFar);
+            return new MethodType(mt.getParameterTypes(), mt.getReturnType(), thrown, syms.methodClass);
         }
-        
+
         boolean isSubtypeInternal(Type s, Type t) {
             return (s.isPrimitive() && t.isPrimitive()) ?
                     isSameType(t, s) :
-                    isSubtypeUnchecked(t, s);
+                    isSubtype(s, t);
         }
     }
 
@@ -1989,6 +1993,10 @@
             @Override
             public Type visitMethodType(MethodType t, Boolean recurse) {
                 Type erasedSig = t.map(recurse ? erasureRecFun : erasureFun);
+                if (erasedSig.getThrownTypes().nonEmpty() && erasedSig.getThrownTypes().head == syms.botType) {
+                    //hack for handling empty union types
+                    erasedSig = createMethodTypeWithThrown(erasedSig, List.<Type>nil());
+                }
                 return createMethodTypeWithTypeArguments(erasedSig, List.<Type>nil());
             }
 
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToInnerClass.java	Thu Nov 03 19:37:56 2011 +0000
@@ -67,8 +67,7 @@
     }
 
     protected LambdaToInnerClass(Context context) {
-        super(context, null);
-        analyzer = new LambdaToInnerAnalyzer();
+        super(context);
         chk = Check.instance(context);
         enter = Enter.instance(context);
     }
@@ -126,12 +125,12 @@
         samMethodDecl.params = params.toList();
 
         samMethodDecl.body = translate(makeLambdaBody(tree, localContext.translatedSym.type.getReturnType()));
-        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl).prependList(List.convert(JCTree.class, capturedFields.toList()));
         localContext.lambdaClassSym.members().enter(samConstrDecl.sym);
         localContext.lambdaClassSym.members().enter(samMethodDecl.sym);
 
-        Env<AttrContext> outerEnv = enter.typeEnvs.get(localContext.lambdaClassSym.owner.enclClass());
-        enter.typeEnvs.put(localContext.lambdaClassSym, enter.classEnv(samClassDecl, outerEnv));
+        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl)
+                .prependList(List.convert(JCTree.class, capturedFields.toList()))
+                .prependList(bridges(samClassDecl));
         
         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
 
@@ -155,7 +154,7 @@
                 List.<JCExpression>nil(),
                 make.QualIdent(tree.targetType.tsym),
                 syntheticInits.toList(),
-                (JCClassDecl)enter.typeEnvs.get(localContext.lambdaClassSym).tree);
+                samClassDecl);
         newClass.constructor = samConstrDecl.sym;
         newClass.setType(localContext.lambdaClassSym.type);
         
@@ -230,27 +229,26 @@
         }
         JCExpression ref_call = null;
         if (tree.mode == ReferenceMode.NEW) {
-            ref_call = make.NewClass(rec, null, tree.getQualifierExpression(), args.toList(), null).setType(tree.getQualifierExpression().type);
+            ref_call = make.NewClass(rec, null, tree.getQualifierExpression(), convertArgs(refSym, args.toList()), null)
+                    .setType(tree.getQualifierExpression().type);
             ((JCNewClass)ref_call).constructor = refSym;
-            if ((refSym.flags() & VARARGS) != 0) {
-                ((JCNewClass)ref_call).varargsElement = types.elemtype(refSym.type.getParameterTypes().last());
-            }
         } else {
             JCExpression meth = rec == null ?
                     make.Ident(refSym) :
                     make.Select(rec, refSym);
-            ref_call = make.Apply(List.<JCExpression>nil(), meth, args.toList(), false).setType(localContext.translatedSym.type.getReturnType());
-            if ((refSym.flags() & VARARGS) != 0) {
-                ((JCMethodInvocation)ref_call).varargsElement = types.elemtype(refSym.type.getParameterTypes().last());
-            }
+            ref_call = make.Apply(List.<JCExpression>nil(), meth,
+                    convertArgs(refSym, args.toList()), false)
+                    .setType(localContext.translatedSym.type.getReturnType());
         }
+        setVarargsIfNeeded(ref_call, refSym);
+        
         samMethodDecl.body = make.Block(0, List.of(ref_call.type.tag == TypeTags.VOID ? make.Exec(ref_call) : make.Return(ref_call)));
-        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl).prependList(List.convert(JCTree.class, capturedFields.toList()));
         localContext.referenceClassSym.members().enter(samConstrDecl.sym);
         localContext.referenceClassSym.members().enter(samMethodDecl.sym);
-
-        Env<AttrContext> outerEnv = enter.typeEnvs.get(localContext.referenceClassSym.owner.enclClass());
-        enter.typeEnvs.put(localContext.referenceClassSym, enter.classEnv(samClassDecl, outerEnv));
+        
+        samClassDecl.defs = List.<JCTree>of(samConstrDecl, samMethodDecl)
+                .prependList(List.convert(JCTree.class, capturedFields.toList()))
+                .prependList(bridges(samClassDecl));
 
         ListBuffer<JCExpression> syntheticInits = ListBuffer.lb();
 
@@ -262,7 +260,7 @@
                 List.<JCExpression>nil(),
                 make.QualIdent(tree.targetType.tsym),
                 syntheticInits.toList(),
-                (JCClassDecl)enter.typeEnvs.get(localContext.referenceClassSym).tree);
+                samClassDecl);
         newClass.constructor = samConstrDecl.sym;
         newClass.setType(localContext.referenceClassSym.type);
         
@@ -273,7 +271,7 @@
         if (localContext.needsReceiverEval()) {
             VarSymbol recVar = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
             JCVariableDecl recDef = make.VarDef(recVar, tree.getQualifierExpression());
-            result = make.LetExpr(recDef, result).setType(types.erasure(tree.targetType));
+            result = make.LetExpr(recDef, result).setType(tree.type);
         }
     }
     // </editor-fold>
@@ -348,11 +346,11 @@
         }
 
         JCExpression meth = make.Select(tree.getQualifierExpression(), tree.sym);
-        JCExpression ref_call = make.Apply(List.<JCExpression>nil(), meth, args.toList(), false).setType(localContext.translatedSym.type.getReturnType());
-        if ((tree.sym.flags() & VARARGS) != 0) {
-            ((JCMethodInvocation)ref_call).varargsElement = types.elemtype(tree.sym.type.getParameterTypes().last());
-        }
-        
+        JCExpression ref_call = make.Apply(List.<JCExpression>nil(), meth,
+                convertArgs(tree.sym, args.toList()), false)
+                .setType(localContext.translatedSym.type.getReturnType());
+        setVarargsIfNeeded(ref_call, tree.sym);
+
         bridgeDecl.body = make.Block(0, List.of(ref_call.type.tag == TypeTags.VOID ? make.Exec(ref_call) : make.Return(ref_call)));
         
         trans_instance = trans_instance.prepend(bridgeDecl);
@@ -363,7 +361,7 @@
         MethodSymbol samDescriptor = types.findDescriptor(targetType.tsym);
         return makeSyntheticMethod(samDescriptor.flags() & ~Flags.ABSTRACT,
                 samDescriptor.name,
-                types.memberType(targetType, samDescriptor),
+                types.erasure(types.memberType(targetType, samDescriptor)),
                 owner);
     }
 
@@ -381,14 +379,9 @@
         chk.compiled.put(functionalClassSym.flatname, functionalClassSym);
 
         functionalClassSym.members_field = new Scope(functionalClassSym);
-
-        if (targetType.isInterface()) {
-            ((ClassType)functionalClassSym.type).supertype_field = syms.objectType;
-            ((ClassType)functionalClassSym.type).interfaces_field = List.of(targetType);
-        }
-        else {
-            ((ClassType)functionalClassSym.type).supertype_field = targetType;
-        }
+        
+        ((ClassType)functionalClassSym.type).supertype_field = syms.objectType;
+        ((ClassType)functionalClassSym.type).interfaces_field = List.of(targetType);
 
         return functionalClassSym;
     }
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Nov 03 19:37:56 2011 +0000
@@ -62,8 +62,7 @@
     }
 
     protected LambdaToMethod(Context context) {
-        super(context, null);
-        analyzer = new LambdaToMethodAnalyzer();
+        super(context);
     }
 
     @Override
@@ -99,7 +98,7 @@
         }
 
         //prepend synthetic args to translated lambda method signature
-        MethodType lambdaType = types.findDescriptor(tree.targetType);
+        MethodType lambdaType = (MethodType)localContext.generatedLambdaSig();
         localContext.translatedSym.type = lambdaType = types.createMethodTypeWithParameters(lambdaType, TreeInfo.types(syntheticParams.toList()));
 
         //create method declaration hoisting the lambda body
@@ -166,7 +165,7 @@
         //finally, compute the type of the indy call
         MethodType indyType =
                 new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
-                               types.erasure(tree.targetType),
+                               tree.type,
                                List.<Type>nil(),
                                syms.methodClass);
 
@@ -211,7 +210,7 @@
         //finally, compute the type of the indy call
         MethodType indyType =
                 new MethodType(List.of(syms.booleanType, new ArrayType(syms.objectType, syms.arrayClass)),
-                               types.erasure(tree.targetType),
+                               tree.type,
                                List.<Type>nil(),
                                syms.methodClass);
 
@@ -223,7 +222,7 @@
         if (localContext.needsReceiverEval()) {
             VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner);
             JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression());
-            result = make.LetExpr(recDef, result).setType(types.erasure(tree.targetType));
+            result = make.LetExpr(recDef, result).setType(tree.type);
         }
     }
     // </editor-fold>
@@ -239,7 +238,7 @@
      * immutability of the attributed lambda body AST.
      */
     private Symbol bridgeLambda(JCLambda tree, LambdaToMethodTranslationContext localContext) {
-        Type samDesc = types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+        Type samDesc = localContext.bridgedLambdaSig();
 
         //generate the parameter list for the bridged member reference - the
         //bridge signature will match the signature of the target sam descriptor
@@ -278,7 +277,8 @@
         select.type = localContext.translatedSym.type;
 
         //create the method call expression
-        JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select, args.toList(), false);
+        JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select,
+                convertArgs(localContext.translatedSym, args.toList()), false);
         apply.type = samDesc.getReturnType();
         
         //the body is either a return expression containing a method call,
@@ -301,7 +301,7 @@
      * to the symbol associated with the method reference to be bridged.
      */
     private Symbol bridgeMemberReference(JCMemberReference tree, ReferenceToMethodTranslationContext localContext) {
-        Type samDesc = types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+        Type samDesc = localContext.bridgedRefSig();
 
         //generate the parameter list for the bridged member reference - the
         //bridge signature will match the signature of the target sam descriptor
@@ -359,14 +359,13 @@
             //create the qualifier expression
             JCFieldAccess select = make.Select(qualifier, tree.sym.name);
             select.sym = tree.sym;
-            select.type = types.memberType(tree.targetType, tree.sym);
+            select.type = localContext.generatedRefSig();
 
             //create the method call expression
-            JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select, args.toList(), false);
+            JCMethodInvocation apply = make.Apply(List.<JCExpression>nil(), select,
+                    convertArgs(tree.sym, args.toList()), false);
             apply.type = samDesc.getReturnType();
-            if ((tree.sym.flags() & VARARGS) != 0) {
-                apply.varargsElement = types.elemtype(tree.sym.type.getParameterTypes().last());
-            }
+            setVarargsIfNeeded(apply, tree.sym);
 
             //the body is either a return expression containing a method call,
             //or the method call itself, depending on whether the return type of
@@ -382,12 +381,13 @@
             //create the instance creation expression
             JCNewClass newClass = make.NewClass(encl,
                                                 List.<JCExpression>nil(),
-                                                make.Type(types.erasure(tree.sym.owner.type)),
-                                                args.toList(),
+                                                make.Type(tree.getQualifierExpression().type),
+                                                convertArgs(tree.sym, args.toList()),
                                                 null);
             newClass.constructor = tree.sym;
             newClass.constructorType = types.memberType(tree.sym.owner.type, tree.sym);
-            newClass.type = types.erasure(tree.sym.owner.type);
+            newClass.type = tree.getQualifierExpression().type;
+            setVarargsIfNeeded(newClass, tree.sym);
 
             //the body is alays a return expression containing an instance creation
             //expression (as a constructor reference cannot be void)
@@ -501,15 +501,21 @@
             }
 
             protected boolean needsBridge() {
-                return !types.isSameType(
-                        types.erasure(types.findDescriptor(tree.targetType)),
-                        types.erasure(types.findDescriptor(tree.targetType.tsym).type));
+                return !types.isSameType(generatedLambdaSig(), bridgedLambdaSig());
             }
 
             @Override
             protected Symbol translate(String name, Symbol sym, LambdaSymbolKind skind) {
-                return makeSyntheticVar(0, name, sym.type, translatedSym);
+                return makeSyntheticVar(0, name, types.erasure(sym.type), translatedSym);
             }
+            
+            protected Type generatedLambdaSig() {
+                return types.erasure(types.findDescriptor(tree.targetType));
+            }
+            
+            protected Type bridgedLambdaSig() {
+                return types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+            }            
         }
 
         class ReferenceToMethodTranslationContext extends ReferenceTranslationContext {
@@ -546,11 +552,19 @@
              */
             protected boolean needsBridge() {
                 boolean sigMismatch = !types.isSameType(
-                        types.erasure(types.findDescriptor(tree.targetType.tsym).type),
-                        types.erasure(types.memberType(tree.targetType, tree.sym)));
+                        generatedRefSig(),
+                        bridgedRefSig());
                 return (isUnbound() || isSpecial() ||
                         sigMismatch);
             }
+            
+            protected Type generatedRefSig() {
+                return types.erasure(tree.sym.type);
+            }
+            
+            protected Type bridgedRefSig() {
+                return types.erasure(types.findDescriptor(tree.targetType.tsym).type);
+            }
         }
     }
     // </editor-fold>
--- a/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/LambdaTranslator.java	Thu Nov 03 19:37:56 2011 +0000
@@ -58,6 +58,7 @@
     protected Resolve rs;
     protected TreeMaker make;
     protected Types types;
+    protected TransTypes transTypes;
     protected Env<AttrContext> attrEnv;
     
     /** list of static methods corresponding to translated static methods
@@ -78,12 +79,13 @@
     protected TranslationContext<?> context;
 
     // <editor-fold defaultstate="collapsed" desc="Instantiating">
-    protected LambdaTranslator(Context context, LambdaAnalyzer analyzer) {
+    protected LambdaTranslator(Context context) {
         names = Names.instance(context);
         syms = Symtab.instance(context);
         rs = Resolve.instance(context);
         make = TreeMaker.instance(context);
         types = Types.instance(context);
+        transTypes = TransTypes.instance(context);
         this.analyzer = makeAnalyzer();
     }
     
@@ -247,18 +249,30 @@
         return body;
     }
     
+    /**
+     * Create new synthetic method with given flags, name, type, owner
+     */
     MethodSymbol makeSyntheticMethod(long flags, String name, Type type, Symbol owner) {
         return new MethodSymbol(flags, names.fromString(name), type, owner);
     }
 
+    /**
+     * Create new synthetic method with given flags, name, type, owner
+     */
     MethodSymbol makeSyntheticMethod(long flags, Name name, Type type, Symbol owner) {
         return new MethodSymbol(flags | SYNTHETIC, name, type, owner);
     }
 
+    /**
+     * Create new synthetic variable with given flags, name, type, owner
+     */
     VarSymbol makeSyntheticVar(long flags, String name, Type type, Symbol owner) {
         return makeSyntheticVar(flags, names.fromString(name), type, owner);
     }
 
+    /**
+     * Create new synthetic variable with given flags, name, type, owner
+     */
     VarSymbol makeSyntheticVar(long flags, Name name, Type type, Symbol owner) {
         return new VarSymbol(flags | SYNTHETIC, name, type, owner);
     }
@@ -275,17 +289,63 @@
         return classLit.setType(erasedClassType);
     }
 
+    /**
+     * Create a 'null' literal
+     */
     JCExpression Null() {
         return make.Literal(TypeTags.BOT, null).setType(syms.botType);
     }
 
+    /**
+     * Create a boolean literal with given value
+     */
     JCExpression Bool(boolean b) {
         return make.Literal(TypeTags.BOOLEAN, b ? 1 : 0).setType(syms.booleanType);
     }
 
+    /**
+     * Create an array of a given type and initializers
+     */
     JCExpression Array(Type elemtype, JCExpression... elems) {
         return make.NewArray(make.Type(elemtype), List.<JCExpression>nil(), List.from(elems)).setType(new ArrayType(elemtype, syms.arrayClass));
     }
+
+    /**
+     * Set varargsElement field on a given tree (must be either a new class tree
+     * or a method call tree)
+     */
+    void setVarargsIfNeeded(JCTree tree, Symbol meth) {
+        Assert.check(meth.kind == Kinds.MTH);
+        if ((meth.flags() & VARARGS) != 0) {
+            Type varargsElement = types.elemtype(meth.type.getParameterTypes().last());
+            switch (tree.getTag()) {
+                case JCTree.APPLY: ((JCMethodInvocation)tree).varargsElement = varargsElement; break;
+                case JCTree.NEWCLASS: ((JCNewClass)tree).varargsElement = varargsElement; break;
+                default: throw new AssertionError();
+            }
+        }
+    }
+    
+    /**
+     * Convert method/constructor arguments by inserting appropriate cast
+     * as required by type-erasure - this is needed when bridging a lambda/method
+     * reference, as the bridged signature might require downcast to be compatible
+     * with the generated signature.
+     */
+    List<JCExpression> convertArgs(Symbol meth, List<JCExpression> args) {
+       Assert.check(meth.kind == Kinds.MTH);
+       List<Type> formals = types.erasure(meth.type).getParameterTypes();
+       Type varargsElem = (meth.flags() & VARARGS) != 0 ?
+               formals.last() : null;
+       return transTypes.translateArgs(args, formals, varargsElem, attrEnv);
+    }
+    
+    /**
+     * Get the set of bridges required for a given class (as per type-erasure)
+     */
+    List<JCTree> bridges(JCClassDecl cdef) {
+        return transTypes.bridges(cdef, attrEnv);
+    }
     // </editor-fold>
     
     // <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
@@ -325,7 +385,6 @@
         protected void analyzeClass(JCClassDecl tree) {
             self = null;
             frameStack = List.nil();
-            contextMap = new HashMap<JCTree, TranslationContext<?>>();
             scan(tree);
         }
 
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Nov 03 19:37:56 2011 +0000
@@ -191,6 +191,20 @@
         }
         return _args;
     }
+    
+    public <T extends JCTree> List<T> translateArgs(List<T> _args,
+                                           List<Type> parameters,
+                                           Type varargsElement,
+                                           Env<AttrContext> localEnv) {
+        Env<AttrContext> prevEnv = env;
+        try {
+            env = localEnv;
+            return translateArgs(_args, parameters, varargsElement);
+        }
+        finally {
+            env = prevEnv;
+        }
+    }
 
     /** Add a bridge definition and enter corresponding method symbol in
      *  local scope of origin.
@@ -415,6 +429,19 @@
 //          if (isSpecialization(l.head))
             addBridges(pos, l.head.tsym, origin, bridges);
     }
+    
+    public List<JCTree> bridges(JCClassDecl cdef, Env<AttrContext> localEnv) {
+        Env<AttrContext> prevEnv = env;
+        try {
+            env = localEnv;
+            ListBuffer<JCTree> bridges = ListBuffer.lb();
+            addBridges(cdef.pos(), cdef.sym, bridges);
+            return bridges.toList();
+        }
+        finally {
+            env = prevEnv;
+        }
+    }
 
 /* ************************************************************************
  * Visitor methods
@@ -770,7 +797,7 @@
 
     public void visitReference(JCMemberReference tree) {
         tree.expr = translate(tree.expr, null);
-        tree.type = syms.methodHandleType;
+        tree.type = erasure(tree.type);
         result = tree;
     }
 
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Nov 03 19:37:56 2011 +0000
@@ -503,9 +503,9 @@
         ENTER(2),
         PROCESS(3),
         ATTR(4),
-        FLOW(5),        
-        UNLAMBDA(6),
-        TRANSTYPES(7),
+        FLOW(5),
+        TRANSTYPES(6),
+        UNLAMBDA(7),
         LOWER(8),
         GENERATE(9);
         
@@ -1293,7 +1293,7 @@
      * The preparation stops as soon as an error is found.
      */
     protected void desugar(final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
-        if (shouldStop(CompileState.UNLAMBDA))
+        if (shouldStop(CompileState.TRANSTYPES))
             return;
 
         if (implicitSourcePolicy == ImplicitSourcePolicy.NONE
@@ -1343,9 +1343,6 @@
                 return;
             }
 
-            env.tree = lambdaTranslator.translateTopLevelClass(env, env.tree, localMake);
-            compileStates.put(env, CompileState.UNLAMBDA);
-
             /**
              * Ensure that superclasses of C are desugared before C itself. This is
              * required for two reasons: (i) as erasure (TransTypes) destroys
@@ -1384,6 +1381,12 @@
 
             env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
             compileStates.put(env, CompileState.TRANSTYPES);
+            
+            if (shouldStop(CompileState.UNLAMBDA))
+                return;
+            
+            env.tree = lambdaTranslator.translateTopLevelClass(env, env.tree, localMake);
+            compileStates.put(env, CompileState.UNLAMBDA);
 
             if (shouldStop(CompileState.LOWER))
                 return;
--- a/test/tools/javac/lambda/sqe/SAM_types/Helper.java	Thu Oct 27 16:41:02 2011 +0100
+++ b/test/tools/javac/lambda/sqe/SAM_types/Helper.java	Thu Nov 03 19:37:56 2011 +0000
@@ -123,9 +123,9 @@
 //SAM type ([Iterable], Iterable<String>/Iterable, {})
 interface QR extends Q, R {}
 
-interface U {List<String> foo(List<String> arg) throws IOException, SQLTransientException;}
+interface U {Collection foo(List<String> arg) throws IOException, SQLTransientException;}
 interface V {List<?> foo(List<String> arg) throws EOFException, SQLException, TimeoutException;}
-interface W {Collection foo(List arg) throws Exception;}
+interface W {List<String> foo(List arg) throws Exception;}
 //SAM type ([List<String>], List<String>/List, {EOFException, SQLTransientException})
 interface UV extends U, V {}
 // SAM type ([List], List<String>/List, {EOFException, SQLTransientException})