changeset 1040:90f2041aa943

Bring the lambda compiler in sync with latest spec draft: *) Add support for poly types/poly expressions *) Add support for deferred attribution of poly expressions *) Improved lambda inference support *) Refactor code towards unification of lambda/method refs *) New inference scheme for wildcards in SAM type *) Add type-parameters to method types *) Unify method checks in Resolve/Infer *) Support re-entrant overload resolution *) Support outwards propagation of constraints/inference variables from lambda body *) Remove support for function type AST *) Remove support for function types
author mcimadamore
date Fri, 20 May 2011 17:19:01 +0100
parents ff3d911a5488
children d7da41f40abf
files src/share/classes/com/sun/source/tree/FunctionTypeTree.java src/share/classes/com/sun/source/tree/Tree.java src/share/classes/com/sun/source/tree/TreeVisitor.java src/share/classes/com/sun/source/util/SimpleTreeVisitor.java src/share/classes/com/sun/source/util/TreeScanner.java src/share/classes/com/sun/tools/apt/mirror/util/TypesImpl.java src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/code/Printer.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/code/Type.java src/share/classes/com/sun/tools/javac/code/TypeTags.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Lower.java src/share/classes/com/sun/tools/javac/comp/MemberEnter.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/comp/TransTypes.java src/share/classes/com/sun/tools/javac/comp/Unlambda.java src/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/share/classes/com/sun/tools/javac/model/JavacTypes.java src/share/classes/com/sun/tools/javac/parser/JavacParser.java src/share/classes/com/sun/tools/javac/resources/compiler.properties src/share/classes/com/sun/tools/javac/tree/JCTree.java src/share/classes/com/sun/tools/javac/tree/Pretty.java src/share/classes/com/sun/tools/javac/tree/TreeCopier.java src/share/classes/com/sun/tools/javac/tree/TreeMaker.java src/share/classes/com/sun/tools/javac/tree/TreeScanner.java src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java test/tools/javac/Diagnostics/6862608/T6862608a.out test/tools/javac/diags/examples.not-yet.txt test/tools/javac/diags/examples/UndeterminedType1.java test/tools/javac/generics/inference/6315770/T6315770.out test/tools/javac/generics/inference/6638712/T6638712a.out test/tools/javac/generics/inference/6638712/T6638712b.out test/tools/javac/generics/inference/6638712/T6638712e.out test/tools/javac/lambda/BadConv01.java test/tools/javac/lambda/BadConv02.java test/tools/javac/lambda/BadConv03.out test/tools/javac/lambda/BadLambdaPos.out test/tools/javac/lambda/BadReturn.out test/tools/javac/lambda/BadTargetType.out test/tools/javac/lambda/FuncType01.java test/tools/javac/lambda/LambdaCapture04.java test/tools/javac/lambda/LambdaCapture05.java test/tools/javac/lambda/LambdaConv02.out test/tools/javac/lambda/LambdaConv03.java test/tools/javac/lambda/LambdaConv04.java test/tools/javac/lambda/LambdaConv09.out test/tools/javac/lambda/LambdaConv10.out test/tools/javac/lambda/LambdaExprNotVoid.out test/tools/javac/lambda/MethodReference04.out test/tools/javac/lambda/MethodReference09.out test/tools/javac/lambda/MethodReference20.out test/tools/javac/lambda/TargetType01.java test/tools/javac/lambda/TargetType01.out test/tools/javac/lambda/TargetType04.out test/tools/javac/lambda/TargetType06.java test/tools/javac/lambda/TargetType06.out test/tools/javac/lambda/TargetType09.java test/tools/javac/lambda/TargetType10.java test/tools/javac/lambda/TargetType10.out test/tools/javac/lambda/TargetType11.java test/tools/javac/lambda/TargetType11.out test/tools/javac/lambda/TargetType14.out test/tools/javac/lambda/TargetType19.java test/tools/javac/lambda/TargetType19.out test/tools/javac/lambda/TargetType20.java test/tools/javac/lambda/badMemberRefBytecode/Main.java test/tools/javac/lambda/sqe/SAM_types/NonSAM1.out test/tools/javac/lambda/sqe/SAM_types/NonSAM3.out test/tools/javac/types/TypeHarness.java
diffstat 76 files changed, 1733 insertions(+), 2444 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/source/tree/FunctionTypeTree.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-/**
- * A tree node for a function type.
- *
- * @author mcimadamore
- */
-public interface FunctionTypeTree extends Tree {
-    List<? extends Tree> getArgumentTypes();
-    List<? extends Tree> getThrownTypes();
-    Tree getResultType();
-}
--- a/src/share/classes/com/sun/source/tree/Tree.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/source/tree/Tree.java	Fri May 20 17:19:01 2011 +0100
@@ -247,11 +247,6 @@
         DISJUNCTIVE_TYPE(DisjunctiveTypeTree.class),
 
         /**
-         * Used for instances of {@link FunctionTypeTree}.
-         */
-        FUNCTION_TYPE(FunctionTypeTree.class),
-
-        /**
          * Used for instances of {@link TypeCastTree}.
          */
         TYPE_CAST(TypeCastTree.class),
--- a/src/share/classes/com/sun/source/tree/TreeVisitor.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/source/tree/TreeVisitor.java	Fri May 20 17:19:01 2011 +0100
@@ -98,7 +98,6 @@
     R visitTry(TryTree node, P p);
     R visitParameterizedType(ParameterizedTypeTree node, P p);
     R visitDisjunctiveType(DisjunctiveTypeTree node, P p);
-    R visitFunctionType(FunctionTypeTree node, P p);
     R visitArrayType(ArrayTypeTree node, P p);
     R visitTypeCast(TypeCastTree node, P p);
     R visitPrimitiveType(PrimitiveTypeTree node, P p);
--- a/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Fri May 20 17:19:01 2011 +0100
@@ -240,10 +240,6 @@
         return defaultAction(node, p);
     }
 
-    public R visitFunctionType(FunctionTypeTree node, P p) {
-        return defaultAction(node, p);
-    }
-
     public R visitTypeParameter(TypeParameterTree node, P p) {
         return defaultAction(node, p);
     }
--- a/src/share/classes/com/sun/source/util/TreeScanner.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/source/util/TreeScanner.java	Fri May 20 17:19:01 2011 +0100
@@ -369,13 +369,6 @@
         return scan(node.getTypeAlternatives(), p);
     }
 
-    public R visitFunctionType(FunctionTypeTree node, P p) {
-        R r = scan(node.getArgumentTypes(), p);
-        r = scanAndReduce(node.getResultType(), p, r);
-        r = scanAndReduce(node.getThrownTypes(), p, r);
-        return r;
-    }
-
     public R visitTypeParameter(TypeParameterTree node, P p) {
         R r = scan(node.getBounds(), p);
         return r;
--- a/src/share/classes/com/sun/tools/apt/mirror/util/TypesImpl.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/apt/mirror/util/TypesImpl.java	Fri May 20 17:19:01 2011 +0100
@@ -80,7 +80,7 @@
      * {@inheritDoc}
      */
     public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
-        return env.jctypes.isAssignableNoCheck(((TypeMirrorImpl) t1).type,
+        return env.jctypes.isAssignable(((TypeMirrorImpl) t1).type,
                                         ((TypeMirrorImpl) t2).type, Warner.noWarnings);
     }
 
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Fri May 20 17:19:01 2011 +0100
@@ -257,32 +257,27 @@
      * (These occur inside java.lang.invoke.MethodHandle.)
      */
     public static final long POLYMORPHIC_SIGNATURE = 1L<<43;
-
-    /**
-     * Flag that marks a lambda that needs a synthetic return statement
-     */
-    public static final long NEEDS_RETURN = 1L<<44;
-
+    
     /**
      * Flag that marks an 'effectively final' local variable
      */
-    public static final long EFFECTIVELY_FINAL = 1L<<45;
+    public static final long EFFECTIVELY_FINAL = 1L<<44;
 
    /**
      * Flag that marks a disjunction var in a multi-catch clause
      */
-    public static final long DISJUNCTION = 1L<<46;
+    public static final long DISJUNCTION = 1L<<45;
 
     /**
      * Flag that marks a special kind of bridge methods (the ones that
      * come from restricted supertype bounds)
      */
-    public static final long OVERRIDE_BRIDGE = 1L<<47;
+    public static final long OVERRIDE_BRIDGE = 1L<<46;
 
     /**
      * Flag that marks non-override equivalent methods with the same signature
      */
-    public static final long CLASH = 1L<<43;
+    public static final long CLASH = 1L<<47;
 
     /** Modifier masks.
      */
--- a/src/share/classes/com/sun/tools/javac/code/Printer.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Printer.java	Fri May 20 17:19:01 2011 +0100
@@ -162,7 +162,7 @@
 
     @Override
     public String visitForAll(ForAll t, Locale locale) {
-        return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
+        return "?" + visit(t.qtype, locale);
     }
 
     @Override
@@ -203,22 +203,6 @@
     }
 
     @Override
-    public String visitFunctionType(FunctionType t, Locale locale) {
-        StringBuilder buf = new StringBuilder();
-        buf.append("#");
-        buf.append(visit(t.restype, locale));
-        buf.append("(");
-        buf.append(printMethodArgs(t.argtypes, false, locale));
-        buf.append(")");
-        if (t.getThrownTypes().nonEmpty()) {
-            buf.append("(");
-            buf.append(visitTypes(t.thrown, locale));
-            buf.append(")");
-        }
-        return buf.toString();
-    }
-
-    @Override
     public String visitDisjunctiveType(DisjunctiveType t, Locale locale) {
         return t.alternatives.toString("|");
     }
@@ -339,7 +323,7 @@
                     ? s.owner.name.toString()
                     : s.name.toString();
             if (s.type != null) {
-                if (s.type.tag == FORALL) {
+                if (s.type.isParameterized()) {
                     ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
                 }
                 ms += "(" + printMethodArgs(
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Fri May 20 17:19:01 2011 +0100
@@ -1072,8 +1072,8 @@
                     ? owner.name.toString()
                     : name.toString();
                 if (type != null) {
-                    if (type.tag == FORALL)
-                        s = "<" + ((ForAll)type).getTypeArguments() + ">" + s;
+                    if (type.isParameterized())
+                        s = "<" + type.getTypeArguments() + ">" + s;
                     s += "(" + type.argtypes((flags() & VARARGS) != 0) + ")";
                 }
                 return s;
--- a/src/share/classes/com/sun/tools/javac/code/Type.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Fri May 20 17:19:01 2011 +0100
@@ -396,9 +396,13 @@
     public boolean isUnbound() { return false; }
     public Type withTypeVar(Type t) { return this; }
 
+    /** The poly tag associated with this type (see TypeTags)
+     */
+    public int getPolyTag() { return NO_POLY; }
+
     /** The underlying method type of this type.
      */
-    public MethodType asMethodType(Types types) { throw new AssertionError(); }
+    public MethodType asMethodType() { throw new AssertionError(); }
 
     /** Complete loading all classes in this type.
      */
@@ -833,113 +837,6 @@
         }
     }
 
-    public static class FunctionType extends ClassType {
-
-        public List<Type> argtypes;
-        public Type restype;
-        public List<Type> thrown;
-
-        public FunctionType(List<Type> argtypes,
-                          Type restype,
-                          List<Type> thrown,
-                          TypeSymbol methodHandleClass) {
-            super(Type.noType, List.<Type>nil(), methodHandleClass);
-            this.argtypes = argtypes;
-            this.restype = restype;
-            this.thrown = thrown;
-        }
-
-        @Override
-        public <R,S> R accept(Type.Visitor<R,S> v, S s) {
-            return v.visitFunctionType(this, s);
-        }
-
-        public String toString() {
-            return "#" + restype + "(" + argtypes + ")" +
-                    (thrown.isEmpty() ? "" : "(" + thrown + ")");
-        }
-
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (!(obj instanceof FunctionType))
-                return false;
-            FunctionType m = (FunctionType)obj;
-            List<Type> args1 = argtypes;
-            List<Type> args2 = m.argtypes;
-            while (!args1.isEmpty() && !args2.isEmpty()) {
-                if (!args1.head.equals(args2.head))
-                    return false;
-                args1 = args1.tail;
-                args2 = args2.tail;
-            }
-            if (!args1.isEmpty() || !args2.isEmpty())
-                return false;
-            return restype.equals(m.restype);
-        }
-
-        public int hashCode() {
-            int h = CLASS;
-            for (List<Type> thisargs = this.argtypes;
-                 thisargs.tail != null; /*inlined: thisargs.nonEmpty()*/
-                 thisargs = thisargs.tail)
-                h = (h << 5) + thisargs.head.hashCode();
-            return (h << 5) + this.restype.hashCode();
-        }
-
-        public List<Type>        getParameterTypes() { return argtypes; }
-        public Type              getReturnType()     { return restype; }
-        public List<Type>        getThrownTypes()    { return thrown; }
-
-        public void setThrown(List<Type> t) {
-            thrown = t;
-        }
-
-        public boolean isErroneous() {
-            return
-                isErroneous(argtypes) ||
-                restype != null && restype.isErroneous();
-        }
-
-        @Override
-        public MethodType asMethodType(Types types) {
-            return new MethodType(argtypes, restype, thrown, types.syms.methodClass);
-        }
-
-        public Type map(Mapping f) {
-            List<Type> argtypes1 = map(argtypes, f);
-            Type restype1 = f.apply(restype);
-            List<Type> thrown1 = map(thrown, f);
-            if (argtypes1 == argtypes &&
-                restype1 == restype &&
-                thrown1 == thrown) return this;
-            else return new FunctionType(argtypes1, restype1, thrown1, tsym);
-        }
-
-        public boolean contains(Type elem) {
-            return elem == this ||
-                    contains(argtypes, elem) ||
-                    restype.contains(elem) ||
-                    thrown.contains(elem);
-        }
-
-        public boolean isFunctionType() {
-            return true;
-        }
-
-        public void complete() {
-            //nothing to do
-        }
-
-        public List<TypeVar> getTypeVariables() {
-            return List.nil();
-        }
-
-        public TypeSymbol asElement() {
-            return null;
-        }
-    }
-
     /** Multiple types used in a throws type parameter */
     public static class DisjunctiveType extends Type {
 
@@ -970,18 +867,38 @@
         public List<Type> argtypes;
         public Type restype;
         public List<Type> thrown;
+        public List<Type> typeargs;
 
         public MethodType(List<Type> argtypes,
                           Type restype,
                           List<Type> thrown,
                           TypeSymbol methodClass) {
+            this(List.<Type>nil(), argtypes, restype, thrown, methodClass);
+        }
+
+        public MethodType(List<Type> typeargs,
+                          List<Type> argtypes,
+                          Type restype,
+                          List<Type> thrown,
+                          TypeSymbol methodClass) {
             super(METHOD, methodClass);
+            this.typeargs = typeargs;
             this.argtypes = argtypes;
             this.restype = restype;
             this.thrown = thrown;
         }
 
         @Override
+        public boolean isParameterized() {
+            return typeargs.nonEmpty();
+        }
+
+        @Override
+        public List<Type> getTypeArguments() {
+            return typeargs;
+        }
+
+        @Override
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitMethodType(this, s);
         }
@@ -992,7 +909,7 @@
          *  should be.
          */
         public String toString() {
-            return "(" + argtypes + ")" + restype;
+            return (isParameterized() ? "<" + typeargs + ">" : "") + "(" + argtypes + ")" + restype;
         }
 
         public boolean equals(Object obj) {
@@ -1047,9 +964,12 @@
             return elem == this || contains(argtypes, elem) || restype.contains(elem);
         }
 
-        public MethodType asMethodType(Types types) { return this; }
+        public MethodType asMethodType() { return this; }
 
         public void complete() {
+            for (List<Type> l = typeargs; l.nonEmpty(); l = l.tail) {
+                ((TypeVar)l.head).bound.complete();
+            }
             for (List<Type> l = argtypes; l.nonEmpty(); l = l.tail)
                 l.head.complete();
             restype.complete();
@@ -1058,7 +978,7 @@
         }
 
         public List<TypeVar> getTypeVariables() {
-            return List.nil();
+            return List.convert(TypeVar.class, getTypeArguments());
         }
 
         public TypeSymbol asElement() {
@@ -1212,14 +1132,58 @@
         public List<Type> allparams() { return qtype.allparams(); }
         public Type getUpperBound() { return qtype.getUpperBound(); }
         public boolean isErroneous() { return qtype.isErroneous(); }
+        public MethodType asMethodType() {
+            Assert.check(qtype.tag == METHOD);
+            return qtype.asMethodType();
+        }
     }
 
-    public static class ForAll extends DelegatedType implements ExecutableType {
-        public List<Type> tvars;
+    /**
+     * A ForAll type is a placeholder for an uninstantiated type - i.e. it is
+     * a polymorphic type that needs to be instantiated against a given
+     * target type. Examples of ForAll types are lambdas, method refernces,
+     * and uninstantiated generic method return types. Note that a polymorphic
+     * type might or might not have type-variables that need to be instantiated.
+     * The act of instantiating a ForAll type against a given target is accomplished
+     * by supplying the target type to the complete() method - this will call
+     * the completer of the ForAll, so that the ForAll type can be instantiated
+     * properly. When a ForAll type has been instantiated, the qtype field
+     * will store the type thos ForAll type has been instantiated to.
+     */
+    public static class ForAll extends DelegatedType {
+        
+        private final int polyTag;
+        public Completer completer;
 
-        public ForAll(List<Type> tvars, Type qtype) {
+        public interface Completer {
+            /**
+             * A Completer is used to instantiate a ForAll type against a
+             * target type. This interface defines a method 'complete()'
+             * that accepts a ForAll, a target type; calling this method
+             * could end up setting the 'qtype' field of the ForAll
+             *
+             * @param fa ForAll to be completed
+             * @param to target type
+             * @return instantiated type
+             */
+            Type complete(ForAll fa, Type to, boolean allowBoxing);
+        }
+
+        public ForAll(int polyTag, Type qtype) {
             super(FORALL, qtype);
-            this.tvars = tvars;
+            this.polyTag = polyTag;
+        }
+
+        public Type complete(Type to, boolean allowBoxing) {
+            if (completer != null) {
+                return completer.complete(this, to, allowBoxing);
+            }
+            return qtype;
+        }
+
+        @Override
+        public int getPolyTag() {
+            return polyTag;
         }
 
         @Override
@@ -1227,77 +1191,10 @@
             return v.visitForAll(this, s);
         }
 
-        public String toString() {
-            return "<" + tvars + ">" + qtype;
-        }
-
-        public List<Type> getTypeArguments()   { return tvars; }
-
         public boolean isErroneous()  {
             return qtype.isErroneous();
         }
 
-        /**
-         * Replaces this ForAll's typevars with a set of concrete Java types
-         * and returns the instantiated generic type. Subclasses should override
-         * in order to check that the list of types is a valid instantiation
-         * of the ForAll's typevars. Since the same ForAll can be instantiated
-         * multiple times (because of overload resolution) and extra-parameter
-         * is used to indicate whether the instantiation is final or not.
-         *
-         * @param actuals list of actual types
-         * @param types types instance
-         * @return qtype where all occurrences of tvars are replaced
-         * by types in actuals
-         */
-        public Type inst(List<Type> actuals, Type to, Types types) {
-            return inst(actuals, to, types, InstantiationPhase.CHECK);
-        }
-        public Type inst(List<Type> actuals, Type to, Types types, InstantiationPhase phase) {
-            return types.subst(qtype, tvars, actuals);
-        }
-        //where
-        public enum InstantiationPhase {
-            RESOLUTION,
-            CHECK;
-        }
-
-        /**
-         * Kind of type-constraint derived during type inference
-         */
-        public enum ConstraintKind {
-            /**
-             * upper bound constraint (a type variable must be instantiated
-             * with a type T, where T is a subtype of all the types specified by
-             * its EXTENDS constraints).
-             */
-            EXTENDS,
-            /**
-             * lower bound constraint (a type variable must be instantiated
-             * with a type T, where T is a supertype of all the types specified by
-             * its SUPER constraints).
-             */
-            SUPER,
-            /**
-             * equality constraint (a type variable must be instantiated to the type
-             * specified by its EQUAL constraint.
-             */
-            EQUAL;
-        }
-
-        /**
-         * Get the type-constraints of a given kind for a given type-variable of
-         * this ForAll type. Subclasses should override in order to return more
-         * accurate sets of constraints.
-         *
-         * @param tv the type-variable for which the constraint is to be retrieved
-         * @param ck the constraint kind to be retrieved
-         * @return the list of types specified by the selected constraint
-         */
-        public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
-            return List.nil();
-        }
-
         public Type map(Mapping f) {
             return f.apply(qtype);
         }
@@ -1305,29 +1202,6 @@
         public boolean contains(Type elem) {
             return qtype.contains(elem);
         }
-
-        public MethodType asMethodType(Types types) {
-            return qtype.asMethodType(types);
-        }
-
-        public void complete() {
-            for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) {
-                ((TypeVar)l.head).bound.complete();
-            }
-            qtype.complete();
-        }
-
-        public List<TypeVar> getTypeVariables() {
-            return List.convert(TypeVar.class, getTypeArguments());
-        }
-
-        public TypeKind getKind() {
-            return TypeKind.EXECUTABLE;
-        }
-
-        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-            return v.visitExecutable(this, p);
-        }
     }
 
     /** A class for instantiatable variables, for use during type
@@ -1482,7 +1356,6 @@
         R visitArrayType(ArrayType t, S s);
         R visitMethodType(MethodType t, S s);
         R visitDisjunctiveType(DisjunctiveType t, S s);
-        R visitFunctionType(FunctionType t, S s);
         R visitPackageType(PackageType t, S s);
         R visitTypeVar(TypeVar t, S s);
         R visitCapturedType(CapturedType t, S s);
--- a/src/share/classes/com/sun/tools/javac/code/TypeTags.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/TypeTags.java	Fri May 20 17:19:01 2011 +0100
@@ -137,4 +137,22 @@
     /** The minimum tag of a partial type
      */
     public static final int firstPartialTag = ERROR;
+
+    /*** POLY TAGS ***/
+
+    /** Poly tag for non-poly types
+     */
+    public static final int NO_POLY = 0;
+
+    /** Poly tag for lambda poly types
+     */
+    public static final int POLY_LAMBDA = NO_POLY + 1;
+
+    /** Poly tag for method references poly types
+     */
+    public static final int POLY_REFERENCE = POLY_LAMBDA + 1;
+
+    /** Poly tag for generic method return types
+     */
+    public static final int POLY_RETURN = POLY_REFERENCE + 1;
 }
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Fri May 20 17:19:01 2011 +0100
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.comp.Check;
 import com.sun.tools.javac.comp.Env;
 import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.comp.Infer;
 import com.sun.tools.javac.comp.AttrContext;
 
 import static com.sun.tools.javac.code.Type.*;
@@ -74,16 +75,16 @@
         new Context.Key<Types>();
 
     final Symtab syms;
+    final Infer infer;
     final JavacMessages messages;
     final Names names;
-    final boolean allowBoxing;
+    final boolean boxingEnabled;
     final boolean allowAbstractClassInSamConversion;
     final ClassReader reader;
     final Source source;
     final Check chk;
     List<Warner> warnStack = List.nil();
     final Name capturedName;
-    final ConversionException conversionException;
 
     // <editor-fold defaultstate="collapsed" desc="Instantiating">
     public static Types instance(Context context) {
@@ -96,14 +97,14 @@
     protected Types(Context context) {
         context.put(typesKey, this);
         syms = Symtab.instance(context);
+        infer = Infer.instance(context);
         names = Names.instance(context);
-        allowBoxing = Source.instance(context).allowBoxing();
+        boxingEnabled = Source.instance(context).allowBoxing();
         reader = ClassReader.instance(context);
         source = Source.instance(context);
         chk = Check.instance(context);
         capturedName = names.fromString("<captured wildcard>");
         messages = JavacMessages.instance(context);
-        conversionException = new ConversionException();
         Options opts = Options.instance(context);
         allowAbstractClassInSamConversion = opts.isSet("abstractSAM");
     }
@@ -121,6 +122,14 @@
     public Type upperBound(Type t) {
         return upperBound.visit(t);
     }
+
+    public List<Type> upperBounds(List<Type> ts) {
+        ListBuffer<Type> buf = lb();
+        for (Type t : ts) {
+            buf.append(upperBound(t));
+        }
+        return buf.toList();
+    }
     // where
         private final MapVisitor<Void> upperBound = new MapVisitor<Void>() {
 
@@ -151,6 +160,14 @@
     public Type lowerBound(Type t) {
         return lowerBound.visit(t);
     }
+
+    public List<Type> lowerBounds(List<Type> ts) {
+        ListBuffer<Type> buf = lb();
+        for (Type t : ts) {
+            buf.append(lowerBound(t));
+        }
+        return buf.toList();
+    }
     // where
         private final MapVisitor<Void> lowerBound = new MapVisitor<Void>() {
 
@@ -274,84 +291,20 @@
 
     // <editor-fold defaultstate="collapsed" desc="isConvertible">
     /**
-     * Is t a subtype of or convertiable via boxing/unboxing/lambda
+     * Is t a subtype of or convertiable via boxing/unboxing
      * convertions to s?
      */
-    public boolean isConvertible(Env<AttrContext> env, Type t, Type s) {
-        return isConvertible(env, t, s, Warner.noWarnings);
-    }
-
-    public boolean isConvertibleNoCheck(Type t, Type s) {
-        return isConvertibleNoCheck(t, s, Warner.noWarnings);
-    }
-    //where
-    private boolean isConvertibleNoCheck(Type t, Type s, Warner warn) {
-        return isConvertible(null, t, s, warn);
-    }
-
-    List<Type> boxedTypesOrTypes(List<Type> ts) {
-        ListBuffer<Type> buf = lb();
-        for (Type t : ts) {
-            buf.append(boxedTypeOrType(t));
+    public boolean isConvertible(Type t, Type s, Warner warn) {
+        boolean tPrimitive = t.isPrimitive();
+        boolean sPrimitive = s.isPrimitive();
+        if (tPrimitive == sPrimitive) {
+            checkUnsafeVarargsConversion(t, s, warn);
+            return isSubtypeUnchecked(t, s, warn);
         }
-        return buf.toList();
-    }
-
-    public boolean isConvertible(Env<AttrContext> env, final Type t, final Type s, final Warner warn) {
-        try {
-            rawIsConvertible(env, t, s, warn);
-            return true;
-        } catch (ConversionException ex) {
-            return false;
-        }
-    }
-    
-    public void rawIsConvertible(Env<AttrContext> env, final Type t, final Type s, final Warner warn) throws ConversionException {
-        if (isFunctionType(t) &&
-                (s.tsym.kind == Kinds.TYP) &&
-                env != null) {
-            final SAMResult samRes = findSAM(s, env);
-            if (samRes.isErroneous()) {
-                throw conversionException.setMessage(samRes.errKey, samRes.args);
-            }
-            Type mtype = samRes.getTargetType();
-            //the order is important here because of type-inference
-            //(reference types first)
-            boolean isReturnOk = t.getReturnType().tag == NONE || (t.getReturnType() == syms.voidType ?
-                (isSameType(mtype.getReturnType(), boxedClass(syms.voidType).type) ||
-                    isSameType(mtype.getReturnType(), syms.voidType)) :
-                (containsType(boxedTypeOrType(mtype.getReturnType()), boxedTypeOrType(t.getReturnType()))) ||
-                covariantReturnType(boxedTypeOrType(t.getReturnType()), boxedTypeOrType(mtype.getReturnType()), Warner.noWarnings));
-
-            boolean argsOk = t.getParameterTypes().size() == mtype.getParameterTypes().size() &&
-                containsType(mtype.getParameterTypes(), t.getParameterTypes());
-
-            boolean thrownOk = t.getThrownTypes() == Type.noTypes ||
-                    chk.unhandled(t.getThrownTypes(), mtype.getThrownTypes()).isEmpty();
-            if (!isReturnOk || !argsOk || !thrownOk) {
-                //target method is not compatible
-                throw conversionException.setMessage("incompatible.target.in.lambda.conv",
-                        samRes.getTargetName(),
-                        Kinds.kindName(s.tsym),
-                        s.tsym);
-            }
-            return;
-        }
-        else {
-            boolean tPrimitive = t.isPrimitive();
-            boolean sPrimitive = s.isPrimitive();
-            if (tPrimitive == sPrimitive) {
-                checkUnsafeVarargsConversion(t, s, warn);
-                if (!isSubtypeUnchecked(t, s, warn)) throw conversionException.setMessage(null);
-                return;
-            }
-            if (!allowBoxing) throw conversionException.setMessage(null);
-            boolean works = tPrimitive
-                ? isSubtype(boxedClass(t).type, s)
-                : isSubtype(unboxedType(t), s);
-            if (!works)
-                throw conversionException.setMessage(null);
-        }
+        if (!boxingEnabled) return false;
+        return tPrimitive
+            ? isSubtype(boxedClass(t).type, s)
+            : isSubtype(unboxedType(t), s);
     }
     //where
     private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
@@ -374,34 +327,14 @@
             warn.warn(LintCategory.VARARGS);
         }
     }
-
     /**
-     * This class is used to keep track of the result of a given conversion.
-     * In order to retrieve a boolean value (success/failure) clients must
-     * supply a type to the 'check' method. This is required as some kinds
-     * of conversion (see lambda conversion) also perform an accessibility
-     * check - as such their outcome depends on the current attribution environment.
-     * This class also stores detailed information about why a type conversion
-     * has failed; this info can be leveraged when a diagnostic message is
-     * generated by javac.
+     * Is t a subtype of or convertiable via boxing/unboxing
+     * convertions to s?
      */
-    public static class ConversionException extends RuntimeException {
-        
-        private String detailsKey;
-        private Object[] detailsArgs;
-
-        public ConversionException setMessage(String key, Object... args) {
-            this.detailsKey = key;
-            this.detailsArgs = args;
-            return this;
-        }
-
-        public JCDiagnostic getDiagnostic(JCDiagnostic.Factory diags) {
-            return detailsKey != null ?
-                diags.fragment(detailsKey, detailsArgs) :
-                null;
-        }
+    public boolean isConvertible(Type t, Type s) {
+        return isConvertible(t, s, Warner.noWarnings);
     }
+    // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="findSam">
 
@@ -592,7 +525,7 @@
                 return targetType;
             } else {
                 if (methodSyms.size() == 1) {
-                    if (methodSyms.head.type.tag == FORALL) {
+                    if (methodSyms.head.type.isParameterized()) {
                         setDiagnostic("invalid.generic.target.for.lambda.conv");
                         return syms.errType;
                     } else if (!isAccessible(methodSyms.head, site)) {
@@ -605,7 +538,7 @@
                 else {
                     // size > 1
                     for (Symbol msym : methodSyms) {
-                        if (msym.type.tag == FORALL) {
+                        if (msym.type.isParameterized()) {
                             setDiagnostic("invalid.generic.target.for.lambda.conv");
                             return syms.errType;
                         } else if (!isAccessible(methodSyms.head, site)) {
@@ -700,68 +633,6 @@
     }
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="normalize">
-
-    /**
-     * Removes toplevel wildcard from a generic classtype. E.g. if T is a
-     * classtype of the kind C< ... , ? super/extends A, ... > this method
-     * finds a type S of the kind C<..., A, ...>. Then, the new type S
-     * is returned (assuming S <: T) otherwise an error type is returned.
-     *
-     * @param t the type to be normalized
-     * @return a type where toplevel wildcards have been removed
-     */
-    public Type normalize(Type t) {
-
-        class Normalizer extends UnaryVisitor<Type> {
-
-            boolean seenTopLevel = false;
-
-            @Override
-            public Type visitClassType(ClassType ct, Void s) {
-                if (!seenTopLevel) {
-                    seenTopLevel = true;
-                    boolean changed = false;
-                    ListBuffer<Type> buf = lb();
-                    for (Type t : ct.getTypeArguments()) {
-                        Type t2 = visit(t);
-                        if (t != t2) changed = true;
-                        buf.append(t2);
-                    }
-                    if (changed)
-                        return new ClassType(ct.getEnclosingType(),
-                                buf.toList(), ct.tsym);
-                }
-                return ct;
-            }
-
-            @Override
-            public Type visitWildcardType(WildcardType t, Void s) {
-                return visit(t.type);
-            }
-
-            @Override
-            public Type visitForAll(ForAll t, Void s) {
-                Type qtype2 = visit(t.qtype);
-                if (qtype2 != t.qtype) {
-                    return new ForAll(t.tvars, qtype2);
-                }
-                return t;
-            }
-
-            public Type visitType(Type t, Void s) {
-                return t;
-            }
-
-        }
-        Type t2 = new Normalizer().visit(t);
-        return isSubtypeUnchecked(t2, t) ?
-            t2 : createErrorType(t);
-    }
-
-
-    // </editor-fold>
-
     // <editor-fold defaultstate="collapsed" desc="isSubtype">
     /**
      * Is t an unchecked subtype of s?
@@ -923,22 +794,6 @@
             }
 
             @Override
-            public Boolean visitFunctionType(FunctionType t, Type s) {
-                if (isFunctionType(s)) {
-                    FunctionType that = (FunctionType)s;
-                    boolean isReturnOk =                            
-                        isSubtype(t.getReturnType(), that.getReturnType());
-                    boolean argsOk = t.getParameterTypes().size() == that.getParameterTypes().size() &&
-                            isSubtypes(that.getParameterTypes(), t.getParameterTypes());
-                    boolean thrownOk = chk.unhandled(t.getThrownTypes(), that.getThrownTypes()).isEmpty();
-                    return isReturnOk && argsOk && thrownOk;
-                }
-                else {
-                    return false;
-                }
-            }
-
-            @Override
             public Boolean visitDisjunctiveType(DisjunctiveType t, Type s) {
                 List<Type> ss = s.tag == DISJOINT ?
                     ((DisjunctiveType)s).alternatives :
@@ -993,10 +848,7 @@
 
                 if (t.inst != null)
                     return isSubtypeNoCapture(t.inst, s); // TODO: ", warn"?
-                else if ((s.isPrimitive() || s.tag == VOID) &&
-                    (t.qtype.tsym.flags() & LAMBDA) != 0) {
-                    t.inst = s;
-                } else {
+                else {
                     t.hibounds = t.hibounds.prepend(s);
                 }
                 return true;
@@ -1186,7 +1038,13 @@
             public Boolean visitMethodType(MethodType t, Type s) {
                 // isSameType for methods does not take thrown
                 // exceptions into account!
-                return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType());
+                if (t.isParameterized() != s.isParameterized()) return false;
+                if (t.isParameterized() &&
+                        !hasSameBounds(t.getTypeArguments(), s.getTypeArguments())) {
+                    return false;
+                }
+                return hasSameArgs(t, subst(s, s.getTypeArguments(), t.getTypeArguments())) &&
+                        visit(t.getReturnType(), subst(s.getReturnType(), s.getTypeArguments(), t.getTypeArguments()));
             }
 
             @Override
@@ -1199,9 +1057,7 @@
                 if (s.tag != FORALL)
                     return false;
 
-                ForAll forAll = (ForAll)s;
-                return hasSameBounds(t, forAll)
-                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
+                return visit(t.qtype, ((ForAll)s).qtype);
             }
 
             @Override
@@ -1456,27 +1312,14 @@
      * s is assumed to be an erased type.<br>
      * (not defined for Method and ForAll types).
      */
-    public boolean isCastable(Env<AttrContext> env, Type t, Type s) {
-        return isCastable(env, t, s, Warner.noWarnings);
+    public boolean isCastable(Type t, Type s) {
+        return isCastable(t, s, Warner.noWarnings);
     }
 
-    public boolean isCastable(Env<AttrContext> env, Type t, Type s, Warner warn) {
+    public boolean isCastable(Type t, Type s, Warner warn) {
         if (t.isPrimitive() != s.isPrimitive())
-            return allowBoxing && (isConvertible(env, t, s, warn) || isConvertible(env, s, t, warn));
-        else if (isConvertible(env, t, s, warn))
-            return true;
-        else
-            return isCastableReference(t, s, warn);
-    }
-
-    public boolean isCastableNoCheck(Type t, Type s) {
-        return isCastableNoCheck(t, s, Warner.noWarnings);
-    }
-    //where
-    private boolean isCastableNoCheck(Type t, Type s, Warner warn) {
-        if (t.isPrimitive() != s.isPrimitive())
-            return allowBoxing && (isConvertibleNoCheck(t, s, warn) || isConvertibleNoCheck(s, t, warn));
-        else if (isConvertibleNoCheck(t, s, warn))
+            return boxingEnabled && (isConvertible(t, s, warn) || isConvertible(s, t, warn));
+        else if (isConvertible(t, s, warn))
             return true;
         else
             return isCastableReference(t, s, warn);
@@ -1530,6 +1373,11 @@
             }
 
             @Override
+            public Boolean visitForAll(ForAll t, Type s) {
+                return true;
+            }
+
+            @Override
             public Boolean visitClassType(ClassType t, Type s) {
                 if (s.tag == ERROR || s.tag == BOT)
                     return true;
@@ -1893,14 +1741,6 @@
         return t.tag == ARRAY;
     }
 
-    public boolean isFunctionType(Type t) {
-        switch (t.tag) {
-            case CLASS: return ((ClassType)t).isFunctionType();
-            case FORALL: return isFunctionType(((ForAll)t).qtype);
-            default: return false;
-        }
-    }
-
     /**
      * The element type of an array.
      */
@@ -2125,19 +1965,8 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="isAssignable">
-    public boolean isAssignable(Env<AttrContext> env, Type t, Type s) {
-        return isAssignable(env, t, s, Warner.noWarnings);
-    }
-
-    //the following methods should be private, but they need to be accessed from
-    //deprecated methods in JavacTypes (for backward compatibility)
-
-    public boolean isAssignableNoCheck(Type t, Type s) {
-        return isAssignableNoCheck(t, s, Warner.noWarnings);
-    }
-    //where
-    public boolean isAssignableNoCheck(Type t, Type s, Warner warner) {
-        return isAssignable(null, t, s, warner);
+    public boolean isAssignable(Type t, Type s) {
+        return isAssignable(t, s, Warner.noWarnings);
     }
 
     /**
@@ -2146,53 +1975,37 @@
      * types.<br>
      * (not defined for Method and ForAll types)
      */
-    /**
-     * Is t assignable to s?<br>
-     * Equivalent to subtype except for constant values and raw
-     * types.<br>
-     * (not defined for Method and ForAll types)
-     */
-    public boolean isAssignable(Env<AttrContext> env, Type t, Type s, Warner warn) {
-        try {
-            rawIsAssignable(env, t, s, warn);
+    public boolean isAssignable(Type t, Type s, Warner warn) {
+        if (t.tag == ERROR)
             return true;
-        } catch(ConversionException ex) {
-            return false;
-        }
-    }
-
-    public void rawIsAssignable(Env<AttrContext> env, Type t, Type s, Warner warn) throws ConversionException {
-        if (t.tag == ERROR)
-            return;
         if (t.tag <= INT && t.constValue() != null) {
             int value = ((Number)t.constValue()).intValue();
             switch (s.tag) {
             case BYTE:
                 if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE)
-                    return;
+                    return true;
                 break;
             case CHAR:
                 if (Character.MIN_VALUE <= value && value <= Character.MAX_VALUE)
-                    return;
+                    return true;
                 break;
             case SHORT:
                 if (Short.MIN_VALUE <= value && value <= Short.MAX_VALUE)
-                    return;
+                    return true;
                 break;
             case INT:
-                return;
+                return true;
             case CLASS:
                 switch (unboxedType(s).tag) {
                 case BYTE:
                 case CHAR:
                 case SHORT:
-                    rawIsAssignable(env, t, unboxedType(s), warn);
-                    return;
+                    return isAssignable(t, unboxedType(s), warn);
                 }
                 break;
             }
         }
-        rawIsConvertible(env, t, s, warn);
+        return isConvertible(t, s, warn);
     }
     // </editor-fold>
 
@@ -2235,11 +2048,6 @@
             }
 
             @Override
-            public Type visitFunctionType(FunctionType t, Boolean recurse) {
-                return syms.methodHandleType;
-            }
-
-            @Override
             public Type visitDisjunctiveType(DisjunctiveType t, Boolean recurse) {
                 return erasure(lub(t.alternatives));
             }
@@ -2863,18 +2671,16 @@
 
             @Override
             public Boolean visitMethodType(MethodType t, Type s) {
-                return s.tag == METHOD
-                    && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
-            }
-
-            @Override
-            public Boolean visitForAll(ForAll t, Type s) {
-                if (s.tag != FORALL)
-                    return strict ? false : visitMethodType(t.asMethodType(Types.this), s);
-
-                ForAll forAll = (ForAll)s;
-                return hasSameBounds(t, forAll)
-                    && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
+                if (s.tag != METHOD ||
+                        (strict && t.isParameterized() != s.isParameterized())) return false;
+
+                if (t.isParameterized() == s.isParameterized() &&
+                            !hasSameBounds(t.getTypeArguments(), s.getTypeArguments())) {
+                    return false;
+                }
+
+                return s.tag == METHOD &&
+                    containsTypeEquivalent(t.argtypes, subst(s.getParameterTypes(), s.getTypeArguments(), t.getTypeArguments()));
             }
 
             @Override
@@ -2882,12 +2688,11 @@
                 return false;
             }
         };
-
-        TypeRelation hasSameArgs_strict = new HasSameArgs(true);
-        TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
-
     // </editor-fold>
 
+    TypeRelation hasSameArgs_strict = new HasSameArgs(true);
+    TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false);
+
     // <editor-fold defaultstate="collapsed" desc="subst">
     public List<Type> subst(List<Type> ts,
                             List<Type> from,
@@ -2950,15 +2755,32 @@
 
         @Override
         public Type visitMethodType(MethodType t, Void ignored) {
+            if (Type.containsAny(to, t.getTypeArguments())) {
+                //perform alpha-renaming of free-variables in 't'
+                //if 'to' types contain variables that are free in 't'
+                List<Type> freevars = newInstances(t.getTypeArguments());
+                t = new MethodType(freevars,
+                        Types.this.subst(t.getParameterTypes(), t.getTypeArguments(), freevars),
+                        Types.this.subst(t.getReturnType(), t.getTypeArguments(), freevars),
+                        Types.this.subst(t.getThrownTypes(), t.getTypeArguments(), freevars),
+                        syms.methodClass);
+            }
+            List<Type> typeargs = substBounds(t.typeargs, from, to);
             List<Type> argtypes = subst(t.argtypes);
             Type restype = subst(t.restype);
             List<Type> thrown = subst(t.thrown);
-            if (argtypes == t.argtypes &&
+            if (typeargs == t.typeargs &&
+                argtypes == t.argtypes &&
                 restype == t.restype &&
                 thrown == t.thrown)
                 return t;
-            else
-                return new MethodType(argtypes, restype, thrown, t.tsym);
+            else {
+                return new MethodType(typeargs,
+                        Types.this.subst(argtypes, t.getTypeArguments(), typeargs),
+                        Types.this.subst(restype, t.getTypeArguments(), typeargs),
+                        Types.this.subst(thrown, t.getTypeArguments(), typeargs),
+                        syms.methodClass);
+            }
         }
 
         @Override
@@ -2995,19 +2817,6 @@
         }
 
         @Override
-        public Type visitFunctionType(FunctionType t, Void ignored) {
-            List<Type> argtypes = subst(t.argtypes);
-            Type restype = subst(t.restype);
-            List<Type> thrown = subst(t.thrown);
-            if (argtypes == t.argtypes &&
-                restype == t.restype &&
-                thrown == t.thrown)
-                return t;
-            else
-                return new FunctionType(argtypes, restype, thrown, t.tsym);
-        }
-
-        @Override
         public Type visitWildcardType(WildcardType t, Void ignored) {
             Type bound = t.type;
             if (t.kind != BoundKind.UNBOUND)
@@ -3031,26 +2840,6 @@
         }
 
         @Override
-        public Type visitForAll(ForAll t, Void ignored) {
-            if (Type.containsAny(to, t.tvars)) {
-                //perform alpha-renaming of free-variables in 't'
-                //if 'to' types contain variables that are free in 't'
-                List<Type> freevars = newInstances(t.tvars);
-                t = new ForAll(freevars,
-                        Types.this.subst(t.qtype, t.tvars, freevars));
-            }
-            List<Type> tvars1 = substBounds(t.tvars, from, to);
-            Type qtype1 = subst(t.qtype);
-            if (tvars1 == t.tvars && qtype1 == t.qtype) {
-                return t;
-            } else if (tvars1 == t.tvars) {
-                return new ForAll(tvars1, qtype1);
-            } else {
-                return new ForAll(tvars1, Types.this.subst(qtype1, t.tvars, tvars1));
-            }
-        }
-
-        @Override
         public Type visitDisjunctiveType(DisjunctiveType t, Void s) {
             List<Type> types1 = subst(t.alternatives);
             return (types1 != t.alternatives) ?
@@ -3123,14 +2912,14 @@
     /**
      * Does t have the same bounds for quantified variables as s?
      */
-    boolean hasSameBounds(ForAll t, ForAll s) {
-        List<Type> l1 = t.tvars;
-        List<Type> l2 = s.tvars;
+    boolean hasSameBounds(List<Type> targs1, List<Type> targs2) {
+        List<Type> l1 = targs1;
+        List<Type> l2 = targs2;
         while (l1.nonEmpty() && l2.nonEmpty() &&
                isSameType(l1.head.getUpperBound(),
                           subst(l2.head.getUpperBound(),
-                                s.tvars,
-                                t.tvars))) {
+                                targs2,
+                                targs1))) {
             l1 = l1.tail;
             l2 = l2.tail;
         }
@@ -3155,53 +2944,25 @@
         };
     // </editor-fold>
 
-    public Type createMethodTypeWithParameters(Type original, List<Type> newParams) {
-        return original.accept(methodWithParameters, newParams);
+    public MethodType createMethodTypeWithTypeArguments(Type original, List<Type> newTypeargs) {
+        Assert.check(original.tag == METHOD);
+        return new MethodType(newTypeargs, original.getParameterTypes(), original.getReturnType(), original.getThrownTypes(), original.tsym);
     }
-    // where
-        private final MapVisitor<List<Type>> methodWithParameters = new MapVisitor<List<Type>>() {
-            public Type visitType(Type t, List<Type> newParams) {
-                throw new IllegalArgumentException("Not a method type: " + t);
-            }
-            public Type visitMethodType(MethodType t, List<Type> newParams) {
-                return new MethodType(newParams, t.restype, t.thrown, t.tsym);
-            }
-            public Type visitForAll(ForAll t, List<Type> newParams) {
-                return new ForAll(t.tvars, t.qtype.accept(this, newParams));
-            }
-        };
-
-    public Type createMethodTypeWithThrown(Type original, List<Type> newThrown) {
-        return original.accept(methodWithThrown, newThrown);
+
+    public MethodType createMethodTypeWithParameters(Type original, List<Type> newParams) {
+        Assert.check(original.tag == METHOD);
+        return new MethodType(original.getTypeArguments(), newParams, original.getReturnType(), original.getThrownTypes(), original.tsym);
     }
-    // where
-        private final MapVisitor<List<Type>> methodWithThrown = new MapVisitor<List<Type>>() {
-            public Type visitType(Type t, List<Type> newThrown) {
-                throw new IllegalArgumentException("Not a method type: " + t);
-            }
-            public Type visitMethodType(MethodType t, List<Type> newThrown) {
-                return new MethodType(t.argtypes, t.restype, newThrown, t.tsym);
-            }
-            public Type visitForAll(ForAll t, List<Type> newThrown) {
-                return new ForAll(t.tvars, t.qtype.accept(this, newThrown));
-            }
-        };
-
-    public Type createMethodTypeWithReturn(Type original, Type newReturn) {
-        return original.accept(methodWithReturn, newReturn);
+
+    public MethodType createMethodTypeWithThrown(Type original, List<Type> newThrown) {
+        Assert.check(original.tag == METHOD);
+        return new MethodType(original.getTypeArguments(), original.getParameterTypes(), original.getReturnType(), newThrown, original.tsym);
     }
-    // where
-        private final MapVisitor<Type> methodWithReturn = new MapVisitor<Type>() {
-            public Type visitType(Type t, Type newReturn) {
-                throw new IllegalArgumentException("Not a method type: " + t);
-            }
-            public Type visitMethodType(MethodType t, Type newReturn) {
-                return new MethodType(t.argtypes, newReturn, t.thrown, t.tsym);
-            }
-            public Type visitForAll(ForAll t, Type newReturn) {
-                return new ForAll(t.tvars, t.qtype.accept(this, newReturn));
-            }
-        };
+
+    public MethodType createMethodTypeWithReturn(Type original, Type newReturn) {
+        Assert.check(original.tag == METHOD);
+        return new MethodType(original.getTypeArguments(), original.getParameterTypes(), newReturn, original.getThrownTypes(), original.tsym);
+    }
 
     // <editor-fold defaultstate="collapsed" desc="createErrorType">
     public Type createErrorType(Type originalType) {
@@ -3292,7 +3053,7 @@
     public String toString(Type t) {
         if (t.tag == FORALL) {
             ForAll forAll = (ForAll)t;
-            return typaramsString(forAll.tvars) + forAll.qtype;
+            return toString(forAll.qtype);
         }
         return "" + t;
     }
@@ -3822,7 +3583,7 @@
             source.allowCovariantReturns() &&
             !t.isPrimitive() &&
             !s.isPrimitive() &&
-            isAssignableNoCheck(t, s, warner);
+            isAssignable(t, s, warner);
     }
     // </editor-fold>
 
@@ -3847,7 +3608,7 @@
      * Return the primitive type corresponding to a boxed type.
      */
     public Type unboxedType(Type t) {
-        if (allowBoxing) {
+        if (boxingEnabled) {
             for (int i=0; i<syms.boxedName.length; i++) {
                 Name box = syms.boxedName[i];
                 if (box != null &&
@@ -3988,16 +3749,6 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Internal utility methods">
-    private List<Type> upperBounds(List<Type> ss) {
-        if (ss.isEmpty()) return ss;
-        Type head = upperBound(ss.head);
-        List<Type> tail = upperBounds(ss.tail);
-        if (head != ss.head || tail != ss.tail)
-            return tail.prepend(head);
-        else
-            return ss;
-    }
-
     private boolean sideCast(Type from, Type to, Warner warn) {
         // We are casting from type $from$ to type $to$, which are
         // non-final unrelated types.  This method
@@ -4414,7 +4165,6 @@
         public R visitArrayType(ArrayType t, S s)       { return visitType(t, s); }
         public R visitMethodType(MethodType t, S s)     { return visitType(t, s); }
         public R visitDisjunctiveType(DisjunctiveType t, S s)  { return visitType(t, s); }
-        public R visitFunctionType(FunctionType t, S s)  { return visitType(t, s); }
         public R visitPackageType(PackageType t, S s)   { return visitType(t, s); }
         public R visitTypeVar(TypeVar t, S s)           { return visitType(t, s); }
         public R visitCapturedType(CapturedType t, S s) { return visitType(t, s); }
@@ -4464,10 +4214,6 @@
             return visitTypeVar(t, s);
         }
         @Override
-        public R visitFunctionType(FunctionType t, S s) {
-            return visitClassType(t, s);
-        }
-        @Override
         public R visitForAll(ForAll t, S s) {
             return visit(t.qtype, s);
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri May 20 17:19:01 2011 +0100
@@ -42,6 +42,7 @@
 import com.sun.tools.javac.code.Attribute.Compound;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.code.Type.ForAll.*;
 import com.sun.tools.javac.code.Type.*;
 
 import com.sun.source.tree.IdentifierTree;
@@ -88,6 +89,13 @@
     final DeferredLintHandler deferredLintHandler;
     final HashMap<JCTree, Env<AttrContext>> lambdaEnvs = new HashMap<JCTree, Env<AttrContext>>();
 
+    enum LambdaCheckKind {
+        RESOLUTION,
+        CHECK;
+    }
+
+    private LambdaCheckKind lambdaCheckKind = LambdaCheckKind.RESOLUTION;
+
     public static Attr instance(Context context) {
         Attr instance = context.get(attrKey);
         if (instance == null)
@@ -121,7 +129,7 @@
         allowGenerics = source.allowGenerics();
         allowVarargs = source.allowVarargs();
         allowEnums = source.allowEnums();
-        allowBoxing = source.allowBoxing();
+        boxingEnabled = source.allowBoxing();
         allowCovariantReturns = source.allowCovariantReturns();
         allowAnonOuterThis = source.allowAnonOuterThis();
         allowStringsInSwitch = source.allowStringsInSwitch();
@@ -156,7 +164,7 @@
 
     /** Switch: support boxing and unboxing?
      */
-    boolean allowBoxing;
+    boolean boxingEnabled;
 
     /** Switch: support covariant result types?
      */
@@ -222,18 +230,25 @@
      *  @param pt       The expected type (or: prototype) of the tree
      */
     Type check(JCTree tree, Type owntype, int ownkind, int pkind, Type pt) {
-        if (owntype.tag != ERROR && pt.tag != METHOD && pt.tag != FORALL) {
-            if ((ownkind & ~pkind) == 0) {
-                owntype = chk.checkType(tree.pos(), env, owntype, pt, errKey);
-            } else {
-                log.error(tree.pos(), "unexpected.type",
-                          kindNames(pkind),
-                          kindName(ownkind));
-                owntype = types.createErrorType(owntype);
+        LambdaCheckKind prevLambdaCheckKind = lambdaCheckKind;
+        try {
+            lambdaCheckKind = LambdaCheckKind.CHECK;
+            if (owntype.tag != ERROR && pt.tag != METHOD) {
+                if ((ownkind & ~pkind) == 0) {
+                    owntype = chk.checkType(tree.pos(), env, owntype, pt, errKey);
+                } else {
+                    log.error(tree.pos(), "unexpected.type",
+                              kindNames(pkind),
+                              kindName(ownkind));
+                    owntype = types.createErrorType(owntype);
+                }
             }
+            tree.type = owntype;
+            return owntype;
         }
-        tree.type = owntype;
-        return owntype;
+        finally {
+            lambdaCheckKind = prevLambdaCheckKind;
+        }
     }
 
     /** Is given blank final variable assignable, i.e. in a scope where it
@@ -540,7 +555,7 @@
         ListBuffer<Type> argtypes = new ListBuffer<Type>();
         for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)
             argtypes.append(chk.checkNonVoid(
-                l.head.pos(), types.upperBound(attribTree(l.head, env, VAL, Infer.anyPoly, "incompatible.types"))));
+                l.head.pos(), attribTree(l.head, env, VAL, Infer.lambdaPoly, "incompatible.types")));
         return argtypes.toList();
     }
 
@@ -1264,9 +1279,9 @@
             if (types.isSameType(thentype, elsetype))
                 return thentype.baseType();
 
-            Type thenUnboxed = (!allowBoxing || thentype.isPrimitive())
+            Type thenUnboxed = (!boxingEnabled || thentype.isPrimitive())
                 ? thentype : types.unboxedType(thentype);
-            Type elseUnboxed = (!allowBoxing || elsetype.isPrimitive())
+            Type elseUnboxed = (!boxingEnabled || elsetype.isPrimitive())
                 ? elsetype : types.unboxedType(elsetype);
 
             // Otherwise, if both arms can be converted to a numeric
@@ -1278,10 +1293,10 @@
                 // short, or char), and the other is an integer constant
                 // that fits into the subrange, return the subrange type.
                 if (thenUnboxed.tag < INT && elseUnboxed.tag == INT &&
-                    types.isAssignable(env, elseUnboxed, thenUnboxed))
+                    types.isAssignable(elseUnboxed, thenUnboxed))
                     return thenUnboxed.baseType();
                 if (elseUnboxed.tag < INT && thenUnboxed.tag == INT &&
-                    types.isAssignable(env, thenUnboxed, elseUnboxed))
+                    types.isAssignable(thenUnboxed, elseUnboxed))
                     return elseUnboxed.baseType();
 
                 for (int i = BYTE; i < VOID; i++) {
@@ -1293,7 +1308,7 @@
             }
 
             // Those were all the cases that could result in a primitive
-            if (allowBoxing) {
+            if (boxingEnabled) {
                 if (thentype.isPrimitive())
                     thentype = types.boxedClass(thentype).type;
                 if (elsetype.isPrimitive())
@@ -1305,7 +1320,7 @@
             if (types.isSubtype(elsetype, thentype))
                 return thentype.baseType();
 
-            if (!allowBoxing || thentype.tag == VOID || elsetype.tag == VOID) {
+            if (!boxingEnabled || thentype.tag == VOID || elsetype.tag == VOID) {
                 log.error(pos, diagKey,
                           thentype, elsetype);
                 return thentype.baseType();
@@ -1419,37 +1434,24 @@
         // Check that there is an enclosing method which is
         // nested within than the enclosing class.
         if (env.enclMethod == null ||
-            (env.enclMethod.sym.owner != env.enclClass.sym &&
-            !env.enclMethod.sym.name.equals(names.lambda))) {
+            env.enclMethod.sym.owner != env.enclClass.sym) {
             log.error(tree.pos(), "ret.outside.meth");
-
         } else {
+            Type typeToCheck = env.enclMethod.sym.type.getReturnType();
+            //lambda expression does not have expected return type (at this stage)
+            if ((env.enclMethod.sym.flags() & LAMBDA) != 0) {
+                typeToCheck = Infer.anyPoly;
+            }
             // Attribute return expression, if it exists, and check that
             // it conforms to result type of enclosing method.
-            Symbol m = env.enclMethod.sym;
-            boolean isLambda = (env.enclMethod.sym.flags() & LAMBDA) != 0;
-            if (m.type.getReturnType().tag == VOID) {
+            if (typeToCheck.tag == VOID) {
                 if (tree.expr != null)
                     log.error(tree.expr.pos(),
                               "cant.ret.val.from.meth.decl.void");
-            } else if (tree.expr == null) {
-                if (!isLambda) {
-                    log.error(tree.pos(), "missing.ret.val");
-                }
-                else {
-                    ((MethodType)m.type).restype = syms.voidType;
-                }
-            } else {
-                attribExpr(tree.expr, env, isLambda ? Type.noType : m.type.getReturnType());
-                if (isLambda) {
-                    if (tree.getExpression().type.tag == VOID) {
-                        log.error(tree.expr.pos(),
-                                  "cant.ret.void.expr");
-                    }
-                    ((MethodType)m.type).restype = m.type.getReturnType() == Type.noType ?
-                        (tree.expr.type == syms.botType ? syms.objectType : tree.expr.type) :
-                        unionType(tree.pos(), null, m.type.getReturnType(), tree.expr.type, "incompatibles.ret.types.in.lambda");
-                }
+            } else if (tree.expr == null && typeToCheck.tag != NONE) {
+                log.error(tree.pos(), "missing.ret.val");
+            } else if (tree.expr != null) {
+                attribExpr(tree.expr, env, typeToCheck);
             }
         }
         result = null;
@@ -1659,8 +1661,7 @@
         /** Obtain a method type with given argument types.
          */
         Type newMethTemplate(List<Type> argtypes, List<Type> typeargtypes) {
-            MethodType mt = new MethodType(argtypes, null, null, syms.methodClass);
-            return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt);
+            return new MethodType(typeargtypes != null ? typeargtypes : List.<Type>nil(), argtypes, null, null, syms.methodClass);
         }
 
     public void visitNewClass(JCNewClass tree) {
@@ -1763,7 +1764,7 @@
             if (inferred != null &&
                     !inferred.isErroneous() &&
                     inferred.tag == CLASS &&
-                    types.isAssignable(localEnv, inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings)) {
+                    types.isAssignable(inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings)) {
                 String key = types.isSameType(clazztype, inferred) ?
                     "diamond.redundant.args" :
                     "diamond.redundant.args.1";
@@ -1902,7 +1903,7 @@
                 tree.constructorType.getReturnType().tag == FORALL) {
             //we need to 'close' open type-variables in the constructor type
             //this can happen if the constructor is passed a lambda expression
-            tree.constructorType.asMethodType(types).restype =
+            tree.constructorType.asMethodType().restype =
                     check(tree, tree.constructorType.getReturnType(), VAL, pkind, syms.voidType);
         }
         result = check(tree, owntype, VAL, pkind, pt);
@@ -1952,7 +1953,7 @@
         }
 
         //dup attribution environment and augment the set of inference variables
-        Env<AttrContext> localEnv = env.dup(tree);
+        Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
         localEnv.info.tvars = clazztype.tsym.type.getTypeArguments();
 
         //if the type of the instance creation expression is a class type
@@ -1989,9 +1990,7 @@
             //type-variables, infer them using the expected type and declared
             //bounds (JLS 15.12.2.8).
             try {
-                clazztype = infer.instantiateExpr(localEnv, (ForAll) clazztype,
-                        pt.tag == NONE ? syms.objectType : pt,
-                        Warner.noWarnings);
+                clazztype = ((ForAll) clazztype).complete(pt.tag == NONE ? syms.objectType : pt, boxingEnabled);
             } catch (Infer.InferenceException ex) {
                 //an error occurred while inferring uninstantiated type-variables
                 log.error(tree.clazz.pos(),
@@ -2095,7 +2094,7 @@
      * also be generated as they are required during lowering (in order to find
      * free-variables used within a lambda expression).
      */
-    Env<AttrContext> lambdaEnvironment(JCLambda tree, final Type targetType) {
+    Env<AttrContext> lambdaEnvironment(Env<AttrContext> env, JCLambda tree, final Type targetType) {
 
         //create synthetic outer class symbol hoisting the lambda
         ClassSymbol lambdaClassSym = makeLambdaClass(env.info.scope.owner,
@@ -2131,7 +2130,7 @@
                 null); // missing defaultValue
 
         lambda.type = lambdaSym.type;
-        lambda.sym = lambdaSym;
+        tree.sym = lambda.sym = lambdaSym;
         outerEnv.enclClass.defs = List.<JCTree>of(lambda);
         Env<AttrContext> newEnv = memberEnter.methodEnv(lambda, outerEnv);
         newEnv.info.scope.owner = lambda.sym;
@@ -2163,18 +2162,10 @@
     }
     //where
     private MethodSymbol makeLambdaSymbol(Type targetType, Symbol owner) {
-        Name lambdaName = names.lambda;
-        long lambdaFlags = SYNTHETIC | LAMBDA;
-        Type lambdaType = null;
-
-        if (!types.isFunctionType(targetType)) {
-            Types.SAMResult samMethod = types.findSAM(targetType, env);
-            lambdaName = samMethod.getTargetName();
-            lambdaFlags = samMethod.getTargetFlags();
-            lambdaType = samMethod.getTargetType();
-        } else {
-            lambdaType = targetType.asMethodType(types);
-        }
+        Types.SAMResult samMethod = types.findSAM(targetType, env);
+        Name lambdaName = samMethod.getTargetName();
+        long lambdaFlags = samMethod.getTargetFlags() | LAMBDA;
+        Type lambdaType = samMethod.getTargetType();
 
         return new MethodSymbol(
                 lambdaFlags,
@@ -2193,43 +2184,36 @@
      * attribution of the lambda expression can proceed normally.
      */
     @Override
-    public void visitLambda(JCLambda that) {
+    public void visitLambda(final JCLambda that) {
         if (!lambdaOrReferenceAllowed(that)) {
             //lambda only allowed in assignment or method invocation/cast context
             log.error(that.pos(), "unexpected.lambda");
+            result = that.type = syms.errType;
+            return;
         }
-        
-        Type typeToCheck = lambdaOrReferenceTargetType(that);
-        if (typeToCheck.tag != NONE) {
-            Type samType = chk.checkSAM(that, typeToCheck, env);
-            if (samType.isErroneous()) {
-                result = that.type = samType;
-                return;
+        final ListBuffer<Type> parameterTypes = ListBuffer.lb();
+        final boolean hasExplicitParameters = !that.needsParameterInference();
+        if (hasExplicitParameters) {
+            for (JCVariableDecl param : that.params) {
+                parameterTypes.append(attribType(param.vartype, env));
             }
         }
 
-        //if the lambda expression needs parameter inference and/or the target
-        //type is unknown (e.g. the lambda position is in argument position)
-        //apply an inference step where lambda return type/thrown types are
-        //inferred from the body of the lambda; otherwise, just attribute the
-        //lambda expression against a given target type.
-        if (typeToCheck.tag == NONE ||
-                that.needsParameterInference()) {
-            inferLambda(that);
-        } else {
-            attribLambda(that, typeToCheck);
-        }
-
-        //if the target type is known (e.g. lambda expression is in assignment,
-        //return statement, etc.) then we need to check the lambda expression type
-        //against the target type --- this will cause inference of uninferred
-        //lambda parameter types (if any).
-        if (typeToCheck.tag != NONE) {
-            chk.checkType(that.pos(), env, that.type, typeToCheck);
-            result = typeToCheck;
-        } else {
-            result = that.type;
-        }
+        final ForAll owntype = new ForAll(POLY_LAMBDA, Type.noType) {
+            @Override
+            public List<Type> getParameterTypes() {
+                if (qtype.tag != NONE) return qtype.getParameterTypes();
+                else
+                    return hasExplicitParameters ? parameterTypes.toList() : null;
+            }
+        };
+        owntype.completer = new SAMDeferredAttribution<JCLambda>(env, that) {
+            @Override
+            Type deferredAttr(Env<AttrContext> attrEnv, JCLambda treeToCheck, Type pt, boolean allowBoxing) {
+                return attribLambda(attrEnv, treeToCheck, pt, allowBoxing);
+            }
+        };
+        result = check(that, owntype, VAL, pkind, pt);
     }
 
     boolean lambdaOrReferenceAllowed(JCTree lambdaOrReference) {
@@ -2263,253 +2247,125 @@
             default: return pt;
         }
     }
-
+    
     /*
-     * Prepare for lambda inference. Replicate the AST and perform a first round
-     * of lambda attribution (see below) in which lambda return/thrown types
-     * are inferred from the lambda body.
+     * Attribute a lambda expression - return type/thrown types of the lambda
+     * expression are inferred from the lambda body.
      */
-    Type inferLambda(final JCLambda that) {
-        ListBuffer<Type> argTypes = ListBuffer.lb();
-        ListBuffer<Type> tvars = ListBuffer.lb();
-        JCLambda tempLambda = new TreeCopier<Object>(make).copy(that);
-
-        //for each empty variable type, create a 'partial' type-variable
-        //this type-variable will be eventually inferred from the target-type
-        for (JCVariableDecl param : tempLambda.params) {
-            if (param.vartype == null) {
-                TypeSymbol tvSym = new TypeSymbol(LAMBDA,
-                        param.name,
-                        null,
-                        env.info.scope.owner);
-                TypeVar tv = new TypeVar(tvSym, Type.noType, null);
-                param.vartype = make.Type(tv);
-                tvSym.type = tv;
-                tvars.append(tv);
-                argTypes.append(tv);
-            }
-            else {
-                argTypes.append(attribType(param.vartype, env));
-            }
-        }
-
-        TypeSymbol tvSym = new TypeSymbol(LAMBDA,
-                        names.fromString("R"),
-                        null,
-                        env.info.scope.owner);
-        TypeVar resType = new TypeVar(tvSym, Type.noType, null);
-
-        Type ft;
+    Type attribLambda(Env<AttrContext> env, JCLambda that, Type target, boolean allowBoxing) {
         
-        try {
-            ft = attribLambda(tempLambda);
-            if (ft.getReturnType() == Type.noType) {
-                tvars.prepend(resType);
-                ft = new FunctionType(ft.getParameterTypes(),
-                        resType, ft.getThrownTypes(), ft.tsym);
-            }
-        } catch(Throwable t) {
-            tvars.prepend(resType);
-            ft = new FunctionType(argTypes.toList(), resType, List.<Type>nil(), syms.methodClass);
-        }
-        final boolean needsReturnTypeInferred = ft.getReturnType() == resType;
-        
-        return that.type = new ForAll(tvars.toList(), ft) {
-            @Override
-            public Type inst(List<Type> actuals, Type to, Types types, ForAll.InstantiationPhase phase) {
-                if (phase == ForAll.InstantiationPhase.CHECK) {
-                    that.type = types.subst(this, tvars, actuals);
-                    if (needsReturnTypeInferred) {
-                        actuals = actuals.tail;
-                    }
-                    //now that we have a target type 'to' and a set of instantiated types
-                    //for each of the unknown lambda parameter types, we can proceed
-                    //with the second phase of lambda attribution (see below).
-                    for (JCVariableDecl param : that.params) {
-                        if (param.vartype == null) {
-                            param.vartype = make.Type(actuals.head);
-                            actuals = actuals.tail;
-                        }
-                    }
-                    attribLambda(that, to);
-                    return that.type;
-                } else {
-                    return super.inst(actuals, to, types, phase);
-                }
-            }
-        };
-    }
-
-    /*
-     * phase 1:
-     * Attribute a lambda expression where the target type is unknown;
-     * return type/thrown types of the lambda expression are inferred from the
-     * lambda body (if possible).
-     */
-    Type attribLambda(JCLambda that) {
-
         //create an environment for attribution of the lambda expression
-        final Env<AttrContext> localEnv = lambdaEnvironment(that,
-                new FunctionType(List.<Type>nil(), Type.noType, List.<Type>nil(), syms.methodHandleType.tsym));
-
-        Type resType = null;
-        ListBuffer<Type> argtypes = ListBuffer.lb();
-
-        boolean prevDeferDiags = log.deferDiagnostics;
-        try {
-            //disable the log -- we need to do this in order to avoid
-            //spurious error messages from this partial attribution sweep
-            log.deferDiagnostics = true;
-            //attribute lambda parameters
-            attribStats(that.params, localEnv);
-            for (JCTree arg : that.params) {
-                argtypes.append(arg.type);
-            }
-
-            if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
-                //the return type is the type of the expression
-                resType = attribExpr(that.getBody(), localEnv);
-            }
-            else {
-                //the return type is the union of all types
-                //returned by the lambda
-                JCBlock body = (JCBlock)that.body;
-                attribStats(body.stats, localEnv);
-                resType = localEnv.info.scope.owner.type.getReturnType();
-                if (resType == null) {
-                    //this happens if the body contains an expression statement
-                    resType = syms.voidType;
+        final Env<AttrContext> localEnv = lambdaEnvironment(env, that, target);
+
+        if (that.needsParameterInference()) {
+            //add param type info in the AST
+            List<Type> actuals = types.findSAM(target, env).getTargetType().getParameterTypes();
+            for (JCVariableDecl param : that.params) {
+                if (param.vartype == null) {
+                    param.vartype = make.Type(actuals.head);
+                    actuals = actuals.tail;
                 }
             }
         }
+
+        //attribute lambda parameters
+        attribStats(that.params, localEnv);
+
+        int prevErrors = log.nerrors;
+
+        LambdaCheckKind prevLambdaCheckKind = lambdaCheckKind;
+        try {
+            lambdaCheckKind = LambdaCheckKind.RESOLUTION;
+
+            if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
+                attribExpr(that.getBody(), localEnv, Infer.anyPoly);
+            }
+            else {
+                JCBlock body = (JCBlock)that.body;
+                attribStats(body.stats, localEnv);
+            }
+        }
         finally {
-            log.deferDiagnostics =  prevDeferDiags;
+            lambdaCheckKind = prevLambdaCheckKind;
         }
 
-        //there are two causes that disable inference of lambda return type:
-        //(i) either the inferred return type is erroneous (meaning that the
-        // body of the lambda contained errors) or (ii) the inferred return type
-        //depends on the type of 'this' (which is unkown at this stage).
-        if (resType.isErroneous() ||
-                resType.contains(localEnv.enclClass.type)) {
-            //give up
-            resType = Type.noType;
+        List<Type> returnTypes = attribLambdaReturnExpressions(localEnv, that, allowBoxing);
+
+        List<Type> thrownTypes = List.nil();
+
+        if (prevErrors == log.nerrors) {
+            //infer thrown types from lambda body
+            flow.analyzeLambda(that, env, make);
+            thrownTypes = that.inferredThrownTypes;
         }
-        else {
-            //infer return type from lambda body
-            resType = resType == syms.botType ?
-                    syms.objectType :
-                    resType;
-        }
+
+        checkSAMCompatible(target, returnTypes, TreeInfo.types(that.params), thrownTypes, allowBoxing);
         
-        List<Type> thrownTypes = null;
-
-        //if one or more 'partial' types were accessed during this first attribution
-        //pass, then thrown types are left uninferred (as e.g. calling an unknown
-        //method on an unknown type might raise unknown exception types).
-        List<JCDiagnostic> deferredErrors = log.getDeferredDiags(JCDiagnostic.Kind.ERROR);
-        if (deferredErrors.nonEmpty()) {
-            ListBuffer<Name> uninferredTypeNames = ListBuffer.lb();
-            for (JCDiagnostic diag : deferredErrors) {
-                searchUninferredTypes(diag, uninferredTypeNames);
-            }
-            if (uninferredTypeNames.nonEmpty() && lambdaInferenceDiags) {
-                String warnKey = uninferredTypeNames.size() == 1 ?
-                    "cyclic.lambda.inference.throws" :
-                    "cyclic.lambda.inference.throws.1";
-                log.warning(that.pos(), warnKey, uninferredTypeNames);
-            }
-            thrownTypes = Type.noTypes;
-            resType = Type.noType;
-        }
-
-        that.type = new FunctionType(argtypes.toList(),
-                resType,
-                thrownTypes,
-                syms.methodHandleType.tsym);
-
-        if (thrownTypes == null) {
-            //infer thrown types from lambda body
-            flow.analyzeLambda(that, localEnv, make);
-        }
-        return that.type;
+        return target;
     }
 
-    void searchUninferredTypes(JCDiagnostic suppressedDiag, ListBuffer<Name> buf) {
-        for (Object o : suppressedDiag.getArgs()) {
-            searchUninferredTypesInArg(o, buf);
+    List<Type> attribLambdaReturnExpressions(Env<AttrContext> env, JCLambda lambda, boolean allowBoxing) {
+        switch (lambda.getBodyKind()) {
+            case EXPRESSION: 
+                Type t = lambda.getBody().type;
+                Type expected = env.enclMethod.type.getReturnType();
+                if (t.tag == FORALL && lambdaCheckKind == LambdaCheckKind.CHECK) {
+                    //instantiate ForAll against expected target
+                    t = lambda.getBody().type = ((ForAll)t).complete(expected, allowBoxing);
+                }
+                return List.of(t);
+            case STATEMENT:
+                JCBlock block = (JCBlock)lambda.getBody();
+                if (block.stats.isEmpty())
+                    return List.<Type>of(syms.voidType);
+                else {
+                    LambdaReturnExprVisitor returnExprScanner =
+                            new LambdaReturnExprVisitor(env, allowBoxing);
+                    returnExprScanner.scan(lambda.getBody());
+                    return returnExprScanner.returnTypes;
+                }
+            default: Assert.error(); return null;
         }
     }
 
-    void searchUninferredTypesInArg(Object o, ListBuffer<Name> buf) {
-        if (o instanceof Type) {
-            Type t = (Type)o;
-            if (t.tsym != null &&
-                    (t.tsym.flags() & LAMBDA) != 0 &&
-                    !buf.contains(t.tsym.name)) {
-                buf.append(t.tsym.name);
-            }
-        } else if (o instanceof TypeSymbol) {
-            TypeSymbol tsym = (TypeSymbol)o;
-            if ((tsym.flags() & LAMBDA) != 0 && !buf.contains(tsym.name)) {
-                buf.append(tsym.name);
-            }
-        } else if (o instanceof JCDiagnostic) {
-            searchUninferredTypes((JCDiagnostic)o, buf);
-        } else if (o instanceof Iterable<?>) {
-            for (Object o2 : (Iterable<?>)o) {
-                searchUninferredTypesInArg(o2, buf);
+    class LambdaReturnExprVisitor extends TreeScanner {
+
+        boolean allowBoxing;
+        List<Type> returnTypes = List.nil();
+        Env<AttrContext> lambdaEnv;
+
+        public LambdaReturnExprVisitor(Env<AttrContext> lambdaEnv, boolean allowBoxing) {
+            this.lambdaEnv = lambdaEnv;
+            this.allowBoxing = allowBoxing;
+        }
+
+        @Override
+        public void visitLambda(JCLambda tree) {
+            //do nothing
+        }
+
+        @Override
+        public void visitClassDef(JCClassDecl tree) {
+            //do nothing
+        }
+
+        @Override
+        public void visitReturn(JCReturn tree) {
+            if (tree.getExpression() != null &&
+                    tree.getExpression().type == syms.voidType) {
+                log.error(tree.getExpression().pos(), "cant.ret.void.expr");
+                returnTypes = returnTypes.prepend(syms.errType);
+            } else {
+                Type t = tree.expr == null ? syms.voidType : tree.expr.type;
+                Type expected = lambdaEnv.enclMethod.type.getReturnType();
+                if (t.tag == FORALL && lambdaCheckKind == LambdaCheckKind.CHECK) {
+                    //instantiate ForAll against expected target
+                    t = tree.expr.type = ((ForAll)t).complete(expected, allowBoxing);
+                }
+                returnTypes = returnTypes.prepend(t);
             }
         }
     }
-
-    /**
-     * phase 2:
-     * Attribute a lambda expression with expected SAM type; return type/thrown
-     * types of the lambda expression are inferred from the target method of the
-     * lambda conversion.
-     */
-    Type attribLambda(JCLambda that, Type samOrFunctionType) {
-
-        //'normalize' the target type (i.e. strip toplevel wildcards, where possible)
-        Type superType = types.normalize(samOrFunctionType);
-
-        //create an environment for attribution of the lambda expression
-        final Env<AttrContext> localEnv = lambdaEnvironment(that, superType);
-
-        //attribute lambda parameters
-        attribStats(that.params, localEnv);
-        ListBuffer<Type> argtypes = ListBuffer.lb();
-        for (JCTree arg : that.params) {
-            argtypes.append(arg.type);
-        }
-
-        Type targetType = localEnv.enclMethod.type;
-
-        //attribute the lambda body
-        if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
-            Type exprType = attribExpr(that.getBody(), localEnv);
-            Type reqType = targetType.getReturnType();
-            if (!(types.isSameType(reqType, types.boxedClass(syms.voidType).type) &&
-                    exprType.tag == VOID)) {
-                //check the expression type against the (possibly inferred) lambda return type
-                chk.checkType(that.getBody(), localEnv, exprType, reqType);
-            }
-        }
-        else {
-            JCBlock body = (JCBlock)that.body;
-            attribStats(body.stats, localEnv);
-        }
-        
-        that.type = new FunctionType(argtypes.toList(),
-                targetType.getReturnType(),
-                targetType.getThrownTypes(),
-                syms.methodHandleType.tsym);
-
-        that.targetType = superType;
-        that.sym = localEnv.enclMethod.sym;
-        return superType;
-    }
     
     public void visitParens(JCParens tree) {
         Type owntype = attribTree(tree.expr, env, pkind, pt);
@@ -2633,7 +2489,7 @@
             // Check that argument types of a reference ==, != are
             // castable to each other, (JLS???).
             if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) {
-                if (!types.isCastable(env, left, right, new Warner(tree.pos()))) {
+                if (!types.isCastable(left, right, new Warner(tree.pos()))) {
                     log.error(tree.pos(), "incomparable.types", left, right);
                 }
             }
@@ -2649,7 +2505,9 @@
         //a fresh environment is required for 292 inference to work properly ---
         //see Infer.instantiatePolymorphicSignatureInstance()
         Env<AttrContext> localEnv = env.dup(tree);
-        Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly);
+        boolean isLambdaOrReference = tree.expr.getTag() == JCTree.LAMBDA ||
+                tree.expr.getTag() == JCTree.REFERENCE; //this will eventually use polyType
+        Type exprtype = attribExpr(tree.expr, localEnv, isLambdaOrReference ? clazztype : Type.noType);
         Type owntype = chk.checkCastable(tree.expr.pos(), env, exprtype, clazztype);
         if (exprtype.constValue() != null)
             owntype = cfolder.coerce(exprtype, owntype);
@@ -2683,7 +2541,7 @@
         boolean varArgs = false;
 
         // Find symbol
-        if (pt.tag == METHOD || pt.tag == FORALL) {
+        if (pt.tag == METHOD) {
             // If we are looking for a method, the prototype `pt' will be a
             // method type with the type of the call's arguments as parameters.
             env.info.varArgs = false;
@@ -2765,75 +2623,180 @@
         result = checkId(tree, env1.enclClass.sym.type, sym, env, pkind, pt, varArgs);
     }
 
-    public void visitReference(JCMemberReference tree) {
-        if (!lambdaOrReferenceAllowed(tree)) {
-            //method references only allowed in assignment or method invocation context
-            log.error(tree.pos(), "unexpected.meth.reference");
+    @Override
+    public void visitReference(final JCMemberReference that) {
+        if (!lambdaOrReferenceAllowed(that)) {
+            //method reference only allowed in assignment or method invocation/cast context
+            log.error(that.pos(), "unexpected.meth.reference");
+            result = that.type = syms.errType;
+            return;
         }
-        Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
-        JCExpression expr = tree.expr;
-        Symbol sym = null;
-        Type owntype = null;
-        switch (tree.mode) {
-            case NEW:
-            case INVOKE:
-                JCMethodInvocation apply = (JCMethodInvocation) expr;
-                Type mtype = attribExpr(apply, localEnv);
-                apply.type = mtype;
-                JCTree base = TreeInfo.getSelector(apply);
-                if (TreeInfo.isStaticSelector(base, names)) {
-                    chk.validate(base, localEnv);
-                }
-                sym = TreeInfo.symbol(apply.meth);
-                owntype = apply.meth.type.isErroneous() ?
-                    apply.meth.type :
-                    makeMethodReferenceType(apply);
-                if (owntype.getReturnType().tag == FORALL) {
-                    throw new AssertionError("references to generic methods are not supported yet");
-                }
-                if (owntype.getReturnType().tag == FORALL) {
-                    //experimental - turned off for now
-                    final ForAll rs = (ForAll)owntype.getReturnType();
-                    owntype = new ForAll(rs.tvars, new FunctionType(owntype.getParameterTypes(),
-                        rs.qtype,
-                        owntype.getThrownTypes(), syms.methodHandleType.tsym)) {
-                        @Override
-                        public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
-                            return rs.getConstraints(tv, ck);
-                        }
-                        @Override
-                        public Type inst(List<Type> actuals, Type to, Types types, ForAll.InstantiationPhase phase) {
-                            rs.inst(actuals, to, types, phase);
-                            return super.inst(actuals, to, types, phase);
-                        }
-                    };
-                }
-                break;
-            default: throw new AssertionError();
+
+        final ListBuffer<Type> parameterTypes = ListBuffer.lb();
+
+        Assert.check(that.mode == JCMemberReference.ReferenceMode.INVOKE ||
+                that.mode == JCMemberReference.ReferenceMode.NEW);
+
+        JCMethodInvocation apply = (JCMethodInvocation) that.expr;
+        final boolean hasExplicitParameters = apply.args != null;
+        if (hasExplicitParameters) {
+            final Env<AttrContext> localEnv = env.dup(that);
+            boolean prevDeferDiagnostics = log.deferDiagnostics;
+            try {
+                log.deferDiagnostics = true;
+                Type ftype = attribMethodReference(localEnv, that, Type.noType, true);
+                parameterTypes.appendList(ftype.getParameterTypes());
+            } finally {
+                log.deferDiagnostics = prevDeferDiagnostics;
+            }
         }
-        // the symbol is resolved
-        assert sym != null;
-        tree.sym = sym;
-        // FIXME: Instantiate MH<R(A...)> with type parameters from sym.
-        result = check(tree, owntype, VAL, pkind, lambdaOrReferenceTargetType(tree));
+
+        final ForAll owntype = new ForAll(POLY_REFERENCE, Type.noType) {
+            @Override
+            public List<Type> getParameterTypes() {
+                if (qtype.tag != NONE) return qtype.getParameterTypes();
+                else
+                    return hasExplicitParameters ? parameterTypes.toList() : null;
+            }
+        };
+        owntype.completer = new SAMDeferredAttribution<JCMemberReference>(env, that) {
+            @Override
+            Type deferredAttr(Env<AttrContext> attrEnv, JCMemberReference treeToCheck, Type pt, boolean allowBoxing) {
+                return attribMethodReference(attrEnv, treeToCheck, pt, allowBoxing);
+            }
+        };
+        result = check(that, owntype, VAL, pkind, pt);
     }
+
     //where
-    private Type makeMethodReferenceType(JCMethodInvocation tree) {
-        JCTree base = TreeInfo.getSelector(tree);
-        Symbol msym = TreeInfo.symbol(tree.meth);
-        Type mtype = tree.meth.type;
+    private Type attribMethodReference(Env<AttrContext> localEnv, final JCMemberReference tree, Type to, boolean allowBoxing) {
+        Assert.check(tree.mode == JCMemberReference.ReferenceMode.INVOKE ||
+                tree.mode == JCMemberReference.ReferenceMode.NEW);
+            
+        JCMethodInvocation apply = (JCMethodInvocation) tree.expr;
+        apply.type = attribExpr(apply, localEnv);
+        JCTree base = TreeInfo.getSelector(apply);
+        if (TreeInfo.isStaticSelector(base, names)) {
+            chk.validate(base, localEnv);
+        }
+        tree.sym = TreeInfo.symbol(apply.meth);
+        Type mtype = apply.meth.type;
+        
+        if (apply.meth.type.isErroneous()) return apply.meth.type;
+
         List<Type> args = mtype.getParameterTypes();
-        if (!msym.isStatic() &&
-                !msym.isConstructor() && 
+        if (!tree.sym.isStatic() &&
+                !tree.sym.isConstructor() &&
                 TreeInfo.isStaticSelector(base, names)) {
             args = args.prepend(base.type);
         }
-        return new FunctionType(args,
-                        msym.isConstructor() ?
-                            base.type :
-                            mtype.getReturnType(),
-                        mtype.getThrownTypes(),
-                        syms.methodHandleType.tsym);
+
+        Type resType = tree.sym.isConstructor() ? base.type : mtype.getReturnType();
+
+        if (to.tag != NONE) {
+            //check mtype against sam descriptor
+            checkSAMCompatible(to, List.of(resType), args, mtype.getThrownTypes(), allowBoxing);
+            return to;
+        } else { //hack to support current inference strategy for method references
+            final List<Type> parameterTypes = args;
+            return new Type(NONE, syms.noSymbol) {
+                @Override
+                public List<Type> getParameterTypes() {
+                    return parameterTypes;
+                }
+            };
+        }
+    }
+
+    /**
+     * SAM compatibility. Check that given return types, thrown types, parameter types
+     * are compatible with the expected SAM descriptor. This means that (i) parameter
+     * types must be identical to those of the target SAM descriptor; (ii) return
+     * types must be compatible with the return type of the expected SAM descriptor;
+     * thrown types must be 'included' in the thown types list of the expected
+     * SAM descriptor.
+     */
+    void checkSAMCompatible(Type sam, List<Type> resultTypes, List<Type> argtypes, List<Type> thrownTypes, boolean allowBoxing) {
+        Types.SAMResult samRes = types.findSAM(sam, env);
+        Type samDescriptor = samRes.getTargetType();
+
+        for (Type resType : resultTypes) {
+            if (!isReturnCompatible(env, resType, samDescriptor.getReturnType(), allowBoxing)) {
+                throw new Infer.InvalidInstanceException(diags).setMessage("infer.incompatible.ret.types.in.lambda", resType);
+            }
+        }
+
+        if (!types.isSameTypes(samDescriptor.getParameterTypes(), argtypes)) {
+            throw new Infer.InvalidInstanceException(diags).setMessage("infer.incompatible.arg.types.in.lambda");
+        }
+
+        if (thrownTypes != Type.noTypes &&
+                chk.unhandled(thrownTypes, samDescriptor.getThrownTypes()).nonEmpty()) {
+            throw new Infer.InvalidInstanceException(diags).setMessage("infer.incompatible.thrown.types.in.lambda", thrownTypes);
+        }
+    }
+
+    /**
+     * A return type t is compatible with an expected return type s if either
+     * (i) t indicates that the lambda body could not return normally,
+     * (ii) t is 'void' and s is void-compatible (see below), (iii) s is 'void'
+     * and t is void-compatible (see below) or (iv) it is possible to
+     * convert t to s via subtyping or assignment conversion.
+     */
+    public boolean isReturnCompatible(Env<AttrContext> env, Type t, Type s, boolean allowBoxing) {
+        t = infer.asUndetType(t);
+        return t.tag == NONE || //can't complete normally
+                t.tag == VOID && isVoidCompatible(s) ||
+                s.tag == VOID && isVoidCompatible(t) ||
+                (allowBoxing ? types.isConvertible(t, s) : types.isSubtypeUnchecked(t, s));
+    }
+
+    /**
+     * A return type in a lambda expression is said to be void-compatible
+     * if it's either 'void' or 'java.lang.Void'
+     */
+    public boolean isVoidCompatible(Type t) {
+        return t.tag == VOID ||
+                types.isSameType(t, types.boxedClass(syms.voidType).type);
+    }
+
+    abstract class SAMDeferredAttribution<T extends JCTree> implements ForAll.Completer {
+
+        Env<AttrContext> baseEnv;
+        T tree;
+
+        public SAMDeferredAttribution(Env<AttrContext> baseEnv, T tree) {
+            this.baseEnv = baseEnv;
+            this.tree = tree;
+        }
+
+        public Type complete(ForAll fa, final Type to, boolean allowBoxing) {
+            Type targetType = null;
+            try {
+                targetType = infer.inferSAM(env, to, fa.getParameterTypes());
+            }
+            catch (Infer.InferenceException ex) {
+                throw new Infer.InferenceException(diags).setMessage("no.suitable.sam.inst", to);
+            }
+            T treeToCheck = lambdaCheckKind == LambdaCheckKind.CHECK ?
+                tree :
+                new TreeCopier<Object>(make).copy(tree);
+            boolean prevDeferDiagnostics = log.deferDiagnostics;
+            try {
+                log.deferDiagnostics = lambdaCheckKind == LambdaCheckKind.RESOLUTION;
+                Type owntype = deferredAttr(baseEnv.dup(tree), treeToCheck, targetType, allowBoxing);
+                if (lambdaCheckKind == LambdaCheckKind.CHECK) {
+                    fa.qtype = owntype;
+                    fa.completer = null;
+                }
+                return owntype;
+            }
+            finally {
+                log.deferDiagnostics = prevDeferDiagnostics;
+            }
+        }
+
+        abstract Type deferredAttr(Env<AttrContext> attrEnv, T t, Type pt, boolean allowBoxing);
     }
 
     public void visitSelect(JCFieldAccess tree) {
@@ -2850,7 +2813,7 @@
         }
 
         // Attribute the qualifier expression, and determine its symbol (if any).
-        Type site = attribTree(tree.selected, env, skind, Infer.anyPoly);
+        Type site = attribTree(tree.selected, env, skind, Type.noType);
         if ((pkind & (PCK | TYP)) == 0)
             site = capture(site); // Capture field access
 
@@ -2875,15 +2838,6 @@
             sitesym != null &&
             sitesym.name == names._super;
 
-        // If selected expression is polymorphic, strip
-        // type parameters and remember in env.info.tvars, so that
-        // they can be added later (in Attr.checkId and Infer.instantiateMethod).
-        if (tree.selected.type.tag == FORALL) {
-            ForAll pstype = (ForAll)tree.selected.type;
-            env.info.tvars = pstype.tvars;
-            site = tree.selected.type = pstype.qtype;
-        }
-
         // Determine the symbol represented by the selection.
         env.info.varArgs = false;
         Symbol sym = selectSym(tree, sitesym, site, env, pt, pkind);
@@ -2968,7 +2922,6 @@
 
         env.info.selectSuper = selectSuperPrev;
         result = checkId(tree, site, sym, env, pkind, pt, varArgs);
-        env.info.tvars = List.nil();
     }
     //where
         /** Determine symbol referenced by a Select expression,
@@ -3001,7 +2954,7 @@
                     pos, location, site, name, true);
             case ARRAY:
             case CLASS:
-                if (pt.tag == METHOD || pt.tag == FORALL) {
+                if (pt.tag == METHOD) {
                     return rs.resolveQualifiedMethod(
                         pos, env, location, site, name, pt.getParameterTypes(), pt.getTypeArguments());
                 } else if (name == names._this || name == names._super) {
@@ -3170,16 +3123,6 @@
                     ? types.memberType(site, sym)
                     : sym.type;
 
-                if (env.info.tvars.nonEmpty()) {
-                    Type owntype1 = new ForAll(env.info.tvars, owntype);
-                    for (List<Type> l = env.info.tvars; l.nonEmpty(); l = l.tail)
-                        if (!owntype.contains(l.head)) {
-                            log.error(tree.pos(), "undetermined.type", owntype1);
-                            owntype1 = types.createErrorType(owntype1);
-                        }
-                    owntype = owntype1;
-                }
-
                 // If the variable is a constant, record constant value in
                 // computed type.
                 if (v.getConstValue() != null && isStaticReference(tree))
@@ -3364,6 +3307,7 @@
                                       typeargtypes,
                                       true,
                                       useVarargs,
+                                      true,
                                       noteWarner);
         boolean warned = noteWarner.hasNonSilentLint(LintCategory.UNCHECKED);
 
@@ -3416,7 +3360,7 @@
                 }
             }
 
-            if (warned && sym.type.tag == FORALL) {
+            if (warned && sym.type.isParameterized()) {
                 chk.warnUnchecked(env.tree.pos(),
                                   "unchecked.meth.invocation.applied",
                                   kindName(sym),
@@ -3453,7 +3397,7 @@
     }
 
     private void assertConvertible(Env<AttrContext> env, JCTree tree, Type actual, Type formal, Warner warn) {
-        if (types.isConvertible(env, actual, formal, warn))
+        if (types.isConvertible(actual, formal, warn))
             return;
 
         if (formal.isCompound()
@@ -3577,15 +3521,6 @@
         tree.type = result = owntype;
     }
 
-    @Override
-    public void visitFunctionType(JCFunctionType tree) {
-        //TODO: add proper checking
-        Type resType = attribType(tree.resultType, env);
-        List<Type> argtypes = attribAnyTypes(tree.argumentTypes, env);
-        List<Type> thrown = attribTypes(tree.thrown, env);
-        result = tree.type = new FunctionType(argtypes, resType, thrown, syms.methodHandleType.tsym);
-    }
-
     public void visitTypeParameter(JCTypeParameter tree) {
         TypeVar a = (TypeVar)tree.type;
         Set<Type> boundSet = new HashSet<Type>();
@@ -4038,9 +3973,6 @@
         @Override
         public void visitLambda(JCLambda that) {
             super.visitLambda(that);
-            if (that.targetType == null) {
-                that.targetType = syms.unknownType;
-            }
             if (that.sym == null) {
                 that.sym = new MethodSymbol(0, names.lambda, syms.unknownType, syms.noSymbol);
             }
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri May 20 17:19:01 2011 +0100
@@ -429,18 +429,12 @@
     Type checkType(DiagnosticPosition pos, Env<AttrContext> env, Type found, Type req, String errKey) {
         if (req.tag == ERROR)
             return req;
-        if (found.tag == FORALL)
+        if (found.getPolyTag() != NO_POLY)
             return instantiatePoly(pos, env, (ForAll)found, req, convertWarner(pos, found, req));
         if (req.tag == NONE)
             return found;
-        JCDiagnostic details = null;
-        try {
-            types.rawIsAssignable(env, found, req, convertWarner(pos, found, req));
+        if (types.isAssignable(found, req, convertWarner(pos, found, req)))
             return found;
-        }
-        catch (Types.ConversionException ex) {
-            details = ex.getDiagnostic(diags);
-        }
         if (found.tag <= DOUBLE && req.tag <= DOUBLE)
             return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
         if (found.isSuperBound()) {
@@ -451,19 +445,7 @@
             log.error(pos, "assignment.to.extends-bound", req);
             return types.createErrorType(found);
         }
-        JCDiagnostic subDiag = details != null ?
-            diags.fragment(errKey + ".1", details) :
-            diags.fragment(errKey);
-        return typeError(pos, subDiag, found, req);
-    }
-
-    boolean checkArgument(Env<AttrContext> env, Type actual, Type formal, boolean allowBoxing, Warner warn) {
-        if (allowBoxing) {
-            types.rawIsConvertible(env, actual, formal, warn);
-            return true;
-        } else {
-            return types.isSubtypeUnchecked(actual, formal, warn);
-        }
+        return typeError(pos, diags.fragment(errKey), found, req);
     }
 
     /** Instantiate polymorphic type to some prototype, unless
@@ -471,38 +453,57 @@
      *  is returned unchanged.
      */
     Type instantiatePoly(DiagnosticPosition pos, Env<AttrContext> env, ForAll t, Type pt, Warner warn) throws Infer.NoInstanceException {
-        if (pt == Infer.anyPoly && complexInference) {
+        if (pt == Infer.anyPoly) {
             return t;
-        } else if (pt == Infer.anyPoly || pt.tag == NONE) {
-            //if type is primitive or function type, the expected type is untouched;
+        }
+        else if (pt == Infer.lambdaPoly &&
+                (t.getPolyTag() == POLY_LAMBDA ||
+                t.getPolyTag() == POLY_REFERENCE)) {
+            return t;
+        } else if (pt.tag == NONE) {
+            //if type is primitive, the expected type is untouched;
             //otherwise changed to java.lang.Object
-            Type newpt = t.qtype.tag <= VOID ||
-                    types.isFunctionType(t) ?
+            Type newpt = t.qtype.tag <= VOID ?
                         t.qtype :
                         syms.objectType;
             return instantiatePoly(pos, env, t, newpt, warn);
         } else if (pt.tag == ERROR) {
             return pt;
         } else {
-            try {
-                return infer.instantiateExpr(env, t, pt, warn, ForAll.InstantiationPhase.CHECK);
-            } catch (Infer.NoInstanceException ex) {
-                if (ex.isAmbiguous) {
-                    JCDiagnostic d = ex.getDiagnostic();
-                    log.error(pos,
-                              "undetermined.type" + (d!=null ? ".1" : ""),
-                              t, d);
-                    return types.createErrorType(pt);
-                } else {
-                    JCDiagnostic d = ex.getDiagnostic();
-                    return typeError(pos,
-                                     diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d),
-                                     t, pt);
-                }
-            } catch (Infer.InvalidInstanceException ex) {
-                JCDiagnostic d = ex.getDiagnostic();
-                log.error(pos, "invalid.inferred.types", d);
-                return types.createErrorType(pt);
+            switch (t.getPolyTag()) {
+                case POLY_REFERENCE:
+                case POLY_LAMBDA:
+                    Types.SAMResult samRes = types.findSAM(pt, env);
+                    if (samRes.isErroneous()) {
+                        return typeError(pos,
+                                diags.fragment("incompatible.types.1", samRes.getDiagnostic(diags)),
+                                t, pt);
+                    }
+                    try {
+                        t.complete(pt, true);
+                        return t;
+                    }
+                    catch (Infer.InferenceException ex) {
+                        return typeError(pos,
+                                diags.fragment("incompatible.types.1", ex.diagnostic),
+                                t, pt);
+                    }
+                case POLY_RETURN:
+                    try {
+                        Type typeToCheck = t.complete(pt, true);
+                        return checkType(warn.pos(), env, typeToCheck, pt);
+                    } catch (Infer.NoInstanceException ex) {
+                        JCDiagnostic d = ex.getDiagnostic();
+                        return typeError(pos,
+                                         diags.fragment("incompatible.types" + (d!=null ? ".1" : ""), d),
+                                         t.qtype, pt);
+                    } catch (Infer.InvalidInstanceException ex) {
+                        JCDiagnostic d = ex.getDiagnostic();
+                        log.error(pos, "invalid.inferred.types", d);
+                        return types.createErrorType(pt);
+                    }
+
+                default: Assert.error("unexpected poly type" + t.getPolyTag()); return null;
             }
         }
     }
@@ -517,7 +518,7 @@
         if (found.tag == FORALL) {
             instantiatePoly(pos, env, (ForAll) found, req, castWarner(pos, found, req));
             return req;
-        } else if (types.isCastable(env, found, req, castWarner(pos, found, req))) {
+        } else if (types.isCastable(found, req, castWarner(pos, found, req))) {
             return req;
         } else {
             return typeError(pos,
@@ -801,8 +802,7 @@
     }
 
     Type checkSAM(DiagnosticPosition pos, Type t, Env<AttrContext> env) {
-        if (t.tag == CLASS &&
-                types.findSAM(t, env).isErroneous()) {
+        if (types.findSAM(t, env).isErroneous()) {
             //if the target type is neither a SAM type nor a function type, reports an error
             Types.SAMResult res = types.findSAM(t, env);
             String key = "invalid.target.type.for.lambda.conv";
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri May 20 17:19:01 2011 +0100
@@ -365,7 +365,8 @@
      *  I.e. is symbol either a local or a blank final variable?
      */
     boolean trackable(VarSymbol sym) {
-        return (sym.owner.kind == MTH ||
+        return !daEnabled ? false :
+            (sym.owner.kind == MTH ||
              ((sym.flags() & (FINAL | HASINIT | PARAMETER)) == FINAL &&
               classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)));
     }
@@ -613,7 +614,7 @@
     /* ------------ Visitor methods for various sorts of trees -------------*/
 
     public void visitClassDef(JCClassDecl tree) {
-        if (tree.sym == null) return;
+        if (!daEnabled || tree.sym == null) return;
 
         JCClassDecl classDefPrev = classDef;
         List<Type> thrownPrev = thrown;
@@ -1336,20 +1337,55 @@
         scanExprs(tree.dims);
         scanExprs(tree.elems);
     }
-    
+
+    /**
+     * It could make sense to create two separate visitors, one for DA/DU and
+     * one for exception checking, as suggested in BGGA - this would make it
+     * easier to check thrown types of a lambda
+     */
     public void analyzeLambda(JCLambda tree, Env<AttrContext> env, TreeMaker make) {
+        JCClassDecl prevClassDef = classDef;
+        Bits prevInits = inits;
+        Bits prevUninits = uninits;
         boolean prevDaEnabled = daEnabled;
+        boolean prevAlive = alive;
+        List<Type> prevThrown = thrown;
+        List<Type> prevCaught = caught;
+        ListBuffer<PendingExit> prevPending = pendingExits;
+        HashMap<Symbol, List<Type>> prevPreciseRethrowTypes = preciseRethrowTypes;
+        Scope prevUnrefdResources = unrefdResources;
         try {
+            classDef = env.enclClass;
+            inits = Bits.emptyBits;
+            uninits = Bits.emptyBits;
             daEnabled = false;
-            analyzeTree(tree, env, make);
+            alive = true;
+            caught = List.of(syms.throwableType); //inhibit exception checking
+            thrown = List.nil();
+            pendingExits = new ListBuffer<PendingExit>();
+            preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
+            unrefdResources = new Scope(classDef.sym);
+            scanStat(tree.body);
+            tree.canCompleteNormally = alive;
+            tree.inferredThrownTypes = thrown;
         }
         finally {
+            classDef = prevClassDef;
+            inits = prevInits;
+            uninits = prevUninits;
             daEnabled = prevDaEnabled;
+            alive = prevAlive;
+            thrown = prevThrown;
+            caught = prevCaught;
+            pendingExits = prevPending;
+            preciseRethrowTypes = prevPreciseRethrowTypes;
+            unrefdResources = prevUnrefdResources;
         }
     }
 
     @Override
     public void visitLambda(JCLambda tree) {
+        if (!daEnabled) return;
         List<Type> prevCaught = caught;
         List<Type> prevThrown = thrown;
         Bits prevUninits = uninits;
@@ -1371,25 +1407,6 @@
             }
             alive = true;
             scanStat(tree.body);
-            
-            if (alive && types.isSameType(tree.type.getReturnType(), types.boxedClass(syms.voidType).type)) {
-                //there's no return statement and the lambda (possibly inferred)
-                //return type is java.lang.Void; sets the NEEDS_RETURN flag in
-                //order to tell code generation to emit a synthetic return statement
-                tree.sym.flags_field |= NEEDS_RETURN;
-                alive = false;
-            }
-
-            if (tree.getBodyKind() == JCLambda.BodyKind.STATEMENT && alive &&
-                    tree.type.getReturnType().tag != VOID &&
-                    tree.type.getReturnType().tag != NONE) {
-                log.error(TreeInfo.diagEndPos(tree.body), "missing.ret.stmt");
-            }
-            if (tree.type.getThrownTypes() == null) {
-                ((FunctionType)tree.type).thrown = thrown;
-                if (alive && tree.type.getReturnType() == Type.noType)
-                    ((FunctionType)tree.type).restype = syms.voidType;
-            }
         }
         finally {
             caught = prevCaught;
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri May 20 17:19:01 2011 +0100
@@ -32,10 +32,8 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Type.ForAll.ConstraintKind;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.JCDiagnostic;
-import java.util.EnumSet;
 
 import static com.sun.tools.javac.code.TypeTags.*;
 
@@ -51,7 +49,9 @@
         new Context.Key<Infer>();
 
     /** A value for prototypes that admit any type, including polymorphic ones. */
+    
     public static final Type anyPoly = new Type(NONE, null);
+    public static final Type lambdaPoly = new Type(NONE, null);
 
     Symtab syms;
     Types types;
@@ -134,6 +134,76 @@
      */
 
     Mapping getInstFun = new Mapping("getInstFun") {
+        public Type apply(Type t) {
+            switch (t.tag) {
+                case UNKNOWN:
+                    throw ambiguousNoInstanceException
+                        .setMessage("undetermined.type");
+                case UNDETVAR:
+                    UndetVar that = (UndetVar) t;
+                    if (that.inst == null)
+                        throw ambiguousNoInstanceException
+                            .setMessage("type.variable.has.undetermined.type",
+                                        that.qtype);
+                    return isConstraintCyclic(that) ?
+                        that.qtype :
+                        apply(that.inst);
+                    default:
+                        return t.map(this);
+            }
+        }
+
+        private boolean isConstraintCyclic(UndetVar uv) {
+            Types.UnaryVisitor<Boolean> constraintScanner =
+                    new Types.UnaryVisitor<Boolean>() {
+
+                List<Type> seen = List.nil();
+
+                Boolean visit(List<Type> ts) {
+                    for (Type t : ts) {
+                        if (visit(t)) return true;
+                    }
+                    return false;
+                }
+
+                public Boolean visitType(Type t, Void ignored) {
+                    return false;
+                }
+
+                @Override
+                public Boolean visitClassType(ClassType t, Void ignored) {
+                    if (t.isCompound()) {
+                        return visit(types.supertype(t)) ||
+                                visit(types.interfaces(t));
+                    } else {
+                        return visit(t.getTypeArguments());
+                    }
+                }
+                @Override
+                public Boolean visitWildcardType(WildcardType t, Void ignored) {
+                    return visit(t.type);
+                }
+
+                @Override
+                public Boolean visitUndetVar(UndetVar t, Void ignored) {
+                    if (seen.contains(t)) {
+                        return true;
+                    } else {
+                        seen = seen.prepend(t);
+                        return visit(t.inst);
+                    }
+                }
+            };
+            return constraintScanner.visit(uv);
+        }
+    };
+
+    /** A mapping that returns its type argument with every UndetVar replaced
+     *  by its `inst' field. If 'inst' is 'null', the mapping returns the
+     *  type-variable 'hidden' behind the UndetVar (what about loops?)
+     */
+
+    Mapping partialInstFun = new Mapping("partialInstFun") {
             public Type apply(Type t) {
                 switch (t.tag) {
                     case UNKNOWN:
@@ -141,62 +211,13 @@
                             .setMessage("undetermined.type");
                     case UNDETVAR:
                         UndetVar that = (UndetVar) t;
-                        if (that.inst == null)
-                            throw ambiguousNoInstanceException
-                                .setMessage("type.variable.has.undetermined.type",
-                                            that.qtype);
-                        return isConstraintCyclic(that) ?
-                            that.qtype :
-                            apply(that.inst);
-                        default:
-                            return t.map(this);
+                        return (that.inst == null || that.inst.tag == BOT)
+                                ? that.qtype : that.inst.map(this);
+                    default:
+                        return t.map(this);
                 }
             }
-
-            private boolean isConstraintCyclic(UndetVar uv) {
-                Types.UnaryVisitor<Boolean> constraintScanner =
-                        new Types.UnaryVisitor<Boolean>() {
-
-                    List<Type> seen = List.nil();
-
-                    Boolean visit(List<Type> ts) {
-                        for (Type t : ts) {
-                            if (visit(t)) return true;
-                        }
-                        return false;
-                    }
-
-                    public Boolean visitType(Type t, Void ignored) {
-                        return false;
-                    }
-
-                    @Override
-                    public Boolean visitClassType(ClassType t, Void ignored) {
-                        if (t.isCompound()) {
-                            return visit(types.supertype(t)) ||
-                                    visit(types.interfaces(t));
-                        } else {
-                            return visit(t.getTypeArguments());
-                        }
-                    }
-                    @Override
-                    public Boolean visitWildcardType(WildcardType t, Void ignored) {
-                        return visit(t.type);
-                    }
-
-                    @Override
-                    public Boolean visitUndetVar(UndetVar t, Void ignored) {
-                        if (seen.contains(t)) {
-                            return true;
-                        } else {
-                            seen = seen.prepend(t);
-                            return visit(t.inst);
-                        }
-                    }
-                };
-                return constraintScanner.visit(uv);
-            }
-        };
+    };
 
 /***************************************************************************
  * Mini/Maximization of UndetVars
@@ -289,77 +310,63 @@
         }
     }
 
+    /** check that type parameters are within their bounds.
+     */
+    void checkWithinBounds(List<Type> tvars,
+                                   List<Type> arguments,
+                                   Warner warn)
+        throws InvalidInstanceException {
+        for (List<Type> tvs = tvars, args = arguments;
+             tvs.nonEmpty();
+             tvs = tvs.tail, args = args.tail) {
+            if (args.head instanceof UndetVar ||
+                    tvars.head.getUpperBound().isErroneous()) continue;
+            List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
+            if (!types.isSubtypeUnchecked(args.head, bounds, warn))
+                throw invalidInstanceException
+                    .setMessage("inferred.do.not.conform.to.bounds",
+                                args.head, bounds);
+        }
+    }
+    
 /***************************************************************************
  * Exported Methods
  ***************************************************************************/
 
-    /** Try to instantiate expression type `that' to given type `to'.
-     *  If a maximal instantiation exists which makes this type
-     *  a subtype of type `to', return the instantiated type.
-     *  If no instantiation exists, or if several incomparable
-     *  best instantiations exist throw a NoInstanceException.
+    // <editor-fold desc="uninferred inference vars instantiation">
+    /**
+     *  Try to instantiate any uninferred inference variable in the current
+     *  inference context, so that the poly type `that' conforms to given type `to'.
+     *  If a maximal instantiation exists the instantiate type-arguments are
+     *  returned.
      */
-    public Type instantiateExpr(Env<AttrContext> env, ForAll that,
+    public List<Type> instantiateExpr(Env<AttrContext> env, ForAll that,
                                 Type to,
                                 Warner warn) throws InferenceException {
-        return instantiateExpr(env, that, to, warn, ForAll.InstantiationPhase.CHECK);
-    }
-    public Type instantiateExpr(Env<AttrContext> env, ForAll that,
-                                Type to,
-                                Warner warn, ForAll.InstantiationPhase phase) throws InferenceException {
-        List<Type> undetvars = Type.map(that.tvars, fromTypeVarFun);
-        for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
-            UndetVar uv = (UndetVar) l.head;
-            TypeVar tv = (TypeVar)uv.qtype;
-            ListBuffer<Type> hibounds = new ListBuffer<Type>();
-            for (Type t : that.getConstraints(tv, ConstraintKind.EXTENDS)) {
-                hibounds.append(types.subst(t, that.tvars, undetvars));
+        try {
+            Assert.check(that.getPolyTag() == POLY_RETURN);
+            Type qtype1 = asUndetType(that.qtype);
+            if (!types.isAssignable(qtype1,
+                   qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
+               throw unambiguousNoInstanceException
+                       .setMessage("infer.no.conforming.instance.exists",
+                                   inferenceVars(), that.qtype, to);
             }
-            List<Type> inst = that.getConstraints(tv, ConstraintKind.EQUAL);
-            if (inst.nonEmpty() && inst.head.tag != BOT) {
-                uv.inst = types.subst(inst.head, that.tvars, undetvars);
+            for (List<Type> l = undetVars(); l.nonEmpty(); l = l.tail)
+                maximizeInst((UndetVar) l.head, warn);
+            // check bounds
+            List<Type> targs = Type.map(undetVars(), getInstFun);
+            if (Type.containsAny(targs, inferenceVars())) {
+                //replace uninferred type-vars
+                targs = types.subst(targs,
+                        inferenceVars(),
+                        instaniateAsUninferredVars(undetVars(), inferenceVars()));
             }
-            uv.hibounds = hibounds.toList();
+            return targs;
         }
-        Type to2 = to.isPrimitive() && !that.qtype.isPrimitive() ?
-            types.boxedClass(to).type :
-            to; //this is a hack
-        Type qtype1 = types.subst(that.qtype, that.tvars, undetvars);
-        boolean works = false;
-        if (types.isFunctionType(qtype1) && to2.tag == CLASS) {
-            //we need conversion - not subtyping (function type needs SAM conversion)
-            works = types.isConvertible(env, qtype1, to2, warn);
-            //inference of function types should take into account lower bounds
-            //(because of contravarance of function type argument types)
-            for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail) {
-                UndetVar uv = (UndetVar) l.head;
-                minimizeInst(uv, warn);
-                if (uv.inst.tag == BOT) {
-                    uv.inst = null;
-                }
-            }
-        } else {
-            works = types.isSubtype(qtype1,
-                qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to2) : to2);
+        finally {
+            inferenceContexts.head.clear();
         }
-        if (!works) {
-            throw unambiguousNoInstanceException
-                .setMessage("infer.no.conforming.instance.exists",
-                            that.tvars, that.qtype, to);
-        }
-        for (List<Type> l = undetvars; l.nonEmpty(); l = l.tail)
-            maximizeInst((UndetVar) l.head, warn);
-        // System.out.println(" = " + qtype1.map(getInstFun));//DEBUG
-
-        // check bounds
-        List<Type> targs = Type.map(undetvars, getInstFun);
-        if (Type.containsAny(targs, that.tvars)) {
-            //replace uninferred type-vars
-            targs = types.subst(targs,
-                    that.tvars,
-                    instaniateAsUninferredVars(undetvars, that.tvars));
-        }
-        return chk.checkType(warn.pos(), env, that.inst(targs, to, types, phase), to);
     }
     //where
     private List<Type> instaniateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
@@ -379,9 +386,31 @@
         }
         return new_targs.toList();
     }
+    // </editor-fold>
 
-    /** Instantiate method type `mt' by finding instantiations of
-     *  `tvars' so that method can be applied to `argtypes'.
+    // <editor-fold desc="method instantiation routines">
+    /**
+     * Instantiate a method type. There are two cases in which a method type
+     * should require instantiation: (i) if the method is generic (i.e. it
+     * has type-parameters) or (ii) if any of the actual types supplied to the
+     * method is a poly type (see Type.ForAll).
+     *
+     * The inference process repeatedly checks actual arguments types against
+     * formal argument types in order to derive constraints on the current
+     * inference variables. Note that checking arguments might trigger completion
+     * of poly types (and, possibly, this can cause deferred attribution).
+     *
+     * The loop terminates when either (i) all arguments have been checked or,
+     * (ii) not all arguments have been checked, but no further progress can be
+     * made. In the latter case an error is issued (cyclic inference).
+     *
+     * It is possible that one or more inference variables are left uninferred
+     * at the end of the checking loop. If this happens, the method return type
+     * is replaced with a poly type, indicating that the method return type
+     * requires additional instantiation - this additional step will be carried
+     * out when i.e. the method return value is assigned to a variable, in which
+     * case, the expected type (of the variable) is used to influence the result
+     * of this second inference pass (see Infer.instantiateExpr).
      */
     public Type instantiateMethod(final Env<AttrContext> env,
                                   List<Type> tvars,
@@ -390,183 +419,125 @@
                                   final List<Type> argtypes,
                                   final boolean allowBoxing,
                                   final boolean useVarargs,
+                                  boolean polyArgs,
                                   final Warner warn) throws InferenceException {
-        //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
-        final ListBuffer<Type> argUndetvars = ListBuffer.lb();
-        List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
-        List<Type> formals = mt.argtypes;
-        boolean forcePostCheck = false;
-        //need to capture exactly once - otherwise subsequent
-        //applicability checks might fail
-        final ListBuffer<Type> capturedArgs = ListBuffer.lb();
-        List<Type> actuals = argtypes;
-        List<Type> actualsNoCapture = argtypes;
-        // instantiate all polymorphic argument types and
-        // set up lower bounds constraints for undetvars
-        Type varargsFormal = useVarargs ? formals.last() : null;
-        if (argtypes != Type.noTypes) {
-			if (varargsFormal == null &&
-		            actuals.size() != formals.size()) {
-		        throw unambiguousNoInstanceException
-		            .setMessage("infer.arg.length.mismatch");
-		    }
-            while (actuals.nonEmpty() && formals.head != varargsFormal) {
-                Type formal = formals.head;
-                Type actual = actuals.head.baseType();
-                Type actualNoCapture = actualsNoCapture.head.baseType();
-                Type undetFormal = types.subst(formal, tvars, undetvars);
-                if (actual.tag == FORALL) {
-                    forcePostCheck = true;
-                    //improvement - go ahead with method conversion check but create
-                    //a 'fake' actual arg, where tvars are replaced with undet var
-                    final ForAll fa = (ForAll)actual;
-                    final List<Type> arg_fvs = Type.map(fa.tvars, fromTypeVarFun);
-                    argUndetvars.appendList(arg_fvs);
-                    actual = types.subst(fa, fa.tvars, arg_fvs);
-                    capturedArgs.append(makeUnknownArgumentForAll(fa, arg_fvs));
-                }
-                else {
-                    capturedArgs.append(actual = types.capture(actual));
-                }
-                boolean works = false;
-                JCDiagnostic problem = null;
-                try {
-                    works = chk.checkArgument(env, actual, undetFormal, allowBoxing, warn);
-                }
-                catch (Types.ConversionException ex) {
-                    problem = ex.getDiagnostic(diags);
-                }
-                if (!works) {
-                    argumentMismatch(tvars, actualNoCapture, formal, problem);
-                }
-                formals = formals.tail;
-                actuals = actuals.tail;
-                actualsNoCapture = actualsNoCapture.tail;
+
+        //init
+        List<Type> uncheckedArgs = List.nil();
+        List<Type> prevUncheckedArgs;
+
+        do {
+            prevUncheckedArgs = uncheckedArgs;
+            uncheckedArgs = rs.checkRawArgumentsAcceptable(env, mt, argtypes,
+                    allowBoxing, useVarargs, warn,
+                    inferenceVars().isEmpty() ? rs.resolveHandler : inferenceHandler);
+                
+            // minimize as yet undetermined type variables
+            for (Type t : undetVars())
+                minimizeInst((UndetVar) t, warn);
+
+            /** Type variables instantiated to bottom */
+            ListBuffer<Type> restvars = new ListBuffer<Type>();
+
+            /** Undet vars instantiated to bottom */
+            final ListBuffer<Type> restundet = new ListBuffer<Type>();
+
+            /** Instantiated types or TypeVars if under-constrained */
+            List<Type> insttypes = List.nil();
+
+            /** Instantiated types or UndetVars if under-constrained */
+            List<Type> undettypes = List.nil();
+
+            for (Type t : undetVars()) {
+                UndetVar uv = (UndetVar)t;
+                Type inst = uv.inst == null ? null : partialInstFun.apply(uv.inst);
+                if (uv.inst == null || uv.inst.tag == BOT) {
+                     restvars.append(uv.qtype);
+                     restundet.append(uv);
+                     insttypes = insttypes.append(uv.qtype);
+                     undettypes = undettypes.append(uv);
+                    uv.inst = null;
+                 } else {
+                    insttypes = insttypes.append(inst);
+                    undettypes = undettypes.append(inst);
+                 }
             }
-            if (formals.head != varargsFormal) // not enough args
-	            throw unambiguousNoInstanceException.setMessage("infer.arg.length.mismatch");
 
-            // for varargs arguments as well
-            if (useVarargs) {
-                //note: if applicability check is triggered by most specific test,
-                //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
-                Type elemType = types.elemtypeOrType(varargsFormal);
-                Type elemUndet = types.subst(elemType, tvars, undetvars);
-                while (actuals.nonEmpty()) {
-                    Type actual = actuals.head.baseType();
-                    Type actualNoCapture = actualsNoCapture.head.baseType();
+            checkWithinBounds(inferenceVars(), undettypes, warn);
 
+            mt = (MethodType)types.subst(mt, inferenceVars(), insttypes);
 
-                    if (actual.tag == FORALL) {
-                        forcePostCheck = true;
-                        //improvement - go ahead with method conversion check but create
-                        //a 'fake' actual arg, where tvars are replaced with undet var
-                        final ForAll fa = (ForAll)actual;
-                        final List<Type> arg_fvs = Type.map(fa.tvars, fromTypeVarFun);
-                        argUndetvars.appendList(arg_fvs);
-                        actual = types.subst(fa, fa.tvars, arg_fvs);
-                        capturedArgs.append(makeUnknownArgumentForAll(fa, arg_fvs));
-                    } else {
-                        capturedArgs.append(actual = types.capture(actual));
-                    }
-                    boolean works = false;
-                    JCDiagnostic problem = null;
-                    try {
-                        works = chk.checkArgument(env, actual, elemUndet, allowBoxing, warn);
-                    }
-                    catch (Types.ConversionException ex) {
-                        problem = ex.getDiagnostic(diags);
-                    }
-                    if (!works) {
-                        argumentMismatch(tvars, actualNoCapture, elemType, problem);
-                    }
-                    actuals = actuals.tail;
-                    actualsNoCapture = actualsNoCapture.tail;
-                }
+            //if no progress has been made, terminate the loop
+            if (prevUncheckedArgs.size() == uncheckedArgs.size() &&
+                    uncheckedArgs.size() > 0) {
+                throw invalidInstanceException.setMessage("cyclic.lambda.inference");
             }
+            tvars = restvars.toList();
         }
+        while (uncheckedArgs.size() > 0 && tvars.nonEmpty());
 
-        // minimize as yet undetermined type variables
-        for (Type t : undetvars.appendList(argUndetvars))
-            minimizeInst((UndetVar) t, warn);
-
-        /** Type variables instantiated to bottom */
-        ListBuffer<Type> restvars = new ListBuffer<Type>();
-
-        /** Undet vars instantiated to bottom */
-        final ListBuffer<Type> restundet = new ListBuffer<Type>();
-
-        /** Instantiated types or TypeVars if under-constrained */
-        ListBuffer<Type> insttypes = new ListBuffer<Type>();
-
-        /** Instantiated types or UndetVars if under-constrained */
-        ListBuffer<Type> undettypes = new ListBuffer<Type>();
-
-        for (Type t : undetvars) {
-            UndetVar uv = (UndetVar)t;
-            while (uv.inst != null && uv.inst.tag == UNDETVAR) {
-                uv = (UndetVar)uv.inst;
-            }
-            if (uv.inst == null) {
-                uv = (UndetVar)t;
-            }
-            if (uv.inst.tag == UNDETVAR || uv.inst.tag == BOT) {
-                restvars.append(uv.qtype);
-                restundet.append(uv);
-                insttypes.append(uv.qtype);
-                undettypes.append(uv);
-                if (uv.inst.tag == BOT)
-                    uv.inst = null;
-            } else {
-                insttypes.append(uv.inst);
-                undettypes.append(uv.inst);
-            }
-        }
-        checkWithinBounds(tvars, undettypes.toList(), warn);
-
-        mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
-
-        if (!restvars.isEmpty() || forcePostCheck) {
+        if (tvars.nonEmpty() || polyArgs) {
             // if there are uninstantiated variables,
             // quantify result type with them
-            final List<Type> inferredTypes = insttypes.toList();
-            final List<Type> all_tvars = tvars; //this is the wrong tvars
-            return new UninferredMethodType(mt, restvars.toList()) {
+            return new UninferredMethodType(env, mt, types) {
                 @Override
-                public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
-                    return Infer.this.getConstraints(restundet.toList(), tv, EnumSet.of(ck), all_tvars, inferredTypes);
-                }
-
-                @Override
-                public void check(List<Type> inferred, Types types, Type to, ForAll.InstantiationPhase phase) throws NoInstanceException {
-                    List<Type> inferred2 = inferred;
-                    for (Type t : restundet.toList()) {
-                        //this has the side-effect of instantiating any
-                        //undetvar in the actual types whose instantiation
-                        //was an uninferred undetvar
-                        UndetVar uv = (UndetVar)t;
-                        uv.inst = inferred2.head;
-                        inferred2 = inferred2.tail;
+                void check(List<Type> inferred) throws NoInstanceException {
+                    // check that actuals conform to inferred formals
+                    try {
+                        rs.checkRawArgumentsAcceptable(env, qtype, argtypes, allowBoxing, useVarargs, warn);
                     }
-                    // check that actuals conform to inferred formals
-                    checkArgumentsAcceptable(env, capturedArgs.toList(), getParameterTypes(), allowBoxing, useVarargs, warn, phase);
+                    catch (Resolve.InapplicableMethodException ex) {
+                        // inferred method is not applicable
+                        throw invalidInstanceException.setMessage(ex.getDiagnostic());
+                    }
                     // check that inferred bounds conform to their bounds
-                    checkWithinBounds(all_tvars,
-                           types.subst(inferredTypes, tvars, inferred), warn);
+                    checkWithinBounds(tvars, inferred, warn);
                     if (useVarargs) {
                         chk.checkVararg(env.tree.pos(), getParameterTypes(), msym);
                     }
             }};
         }
         else {
-            // check that actuals conform to inferred formals
-            checkArgumentsAcceptable(env, capturedArgs.toList(), mt.getParameterTypes(), allowBoxing, useVarargs, warn, ForAll.InstantiationPhase.RESOLUTION);
+            //no rest vars - clear inference context
+            inferenceContexts.head.clear();
+            try {
+                // check that actuals conform to inferred formals
+                rs.checkRawArgumentsAcceptable(env, mt, argtypes, allowBoxing, useVarargs, warn);
+            }
+            catch (Resolve.InapplicableMethodException ex) {
+                // inferred method is not applicable
+                throw invalidInstanceException.setMessage(ex.getDiagnostic());
+            }
             // return instantiated version of method type
             return mt;
         }
     }
     //where
 
+        /** inference check handler **/
+        Resolve.MethodCheckHandler inferenceHandler = new Resolve.MethodCheckHandler() {
+                public void arityMismatch() {
+                    throw unambiguousNoInstanceException.setMessage("infer.arg.length.mismatch");
+                }
+                public void argumentMismatch(boolean varargs, Type found, Type expected, JCDiagnostic cause) {
+                    String key = null;
+                    if (varargs) {
+                        key = cause == null ?
+                            "infer.varargs.argument.mismatch" :
+                            "infer.varargs.argument.mismatch.1";
+                    } else {
+                        key = cause == null ?
+                            "infer.no.conforming.assignment.exists" :
+                            "infer.no.conforming.assignment.exists.1";
+                    }
+                    throw unambiguousNoInstanceException.setMessage(key,
+                            inferenceVars(), found, expected, cause);
+                }
+                public void inaccessibleVarargs(Symbol location, Type expected) {
+                    //this kind of error should not be acted upon at this stage
+                }
+        };
+
         /**
          * A delegated type representing a partially uninferred method type.
          * The return type of a partially uninferred method type is a ForAll
@@ -576,16 +547,18 @@
         abstract class UninferredMethodType extends DelegatedType {
 
             final List<Type> tvars;
+            Env<AttrContext> env;
 
-            public UninferredMethodType(MethodType mtype, List<Type> tvars) {
-                super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
-                this.tvars = tvars;
-                asMethodType(types).restype = new UninferredReturnType(tvars, mtype.restype);
+            public UninferredMethodType(Env<AttrContext> env, Type mt, Types types) {
+                super(METHOD, new MethodType(mt.getParameterTypes(), null, mt.getThrownTypes(), mt.tsym));
+                this.tvars = inferenceVars();
+                this.env = env;
+                asMethodType().restype = new UninferredReturnType(env, mt.getReturnType(), types);
             }
 
             @Override
-            public MethodType asMethodType(Types types) {
-                return qtype.asMethodType(types);
+            public MethodType asMethodType() {
+                return qtype.asMethodType();
             }
 
             @Override
@@ -593,152 +566,134 @@
                 return qtype.map(f);
             }
 
-            void instantiateReturnType(Type restype, List<Type> inferred, Type to, Types types, ForAll.InstantiationPhase phase) throws NoInstanceException {
+            void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
                 //update method type with newly inferred type-arguments
                 qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
                                        restype,
                                        types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred),
                                        UninferredMethodType.this.qtype.tsym);
-                check(inferred, types, to, phase);
+                check(inferred);
             }
 
-            abstract void check(List<Type> inferred, Types types, Type to, ForAll.InstantiationPhase phase) throws NoInstanceException;
-
-            abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck);
+            abstract void check(List<Type> inferred) throws NoInstanceException;
 
             class UninferredReturnType extends ForAll {
-                public UninferredReturnType(List<Type> tvars, Type restype) {
-                    super(tvars, restype);
-                }
-                @Override
-                public Type inst(List<Type> actuals, Type to, Types types, ForAll.InstantiationPhase phase) {
-                    Type newRestype = super.inst(actuals, to, types, phase);
-                    instantiateReturnType(newRestype, actuals, to, types, phase);
-                    return newRestype;
-                }
-                @Override
-                public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
-                    return UninferredMethodType.this.getConstraints(tv, ck);
-                }
-            }
-        }
-
-        private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
-                boolean allowBoxing, boolean useVarargs, Warner warn, ForAll.InstantiationPhase phase) {
-            try {
-                rs.checkRawArgumentsAcceptable(env, actuals, formals,
-                       allowBoxing, useVarargs, warn, phase);
-            }
-            catch (Resolve.InapplicableMethodException ex) {
-                // inferred method is not applicable
-                throw invalidInstanceException.setMessage(ex.getDiagnostic());
-            }
-        }
-    private ForAll makeUnknownArgumentForAll(final ForAll fa, final List<Type> undetvars) {
-        return new ForAll(fa.tvars, fa.qtype) {
-            @Override
-            public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
-                return Infer.this.getConstraints(undetvars, tv, EnumSet.of(ck), fa.tvars, undetvars);
-            }
-            @Override
-            public Type inst(List<Type> actuals, Type to, Types types, ForAll.InstantiationPhase phase) {
-                return fa.inst(actuals, to, types, phase);
-            }
-        };
-    }
-    //where
-    private void argumentMismatch(List<Type> tvars, Type actual, Type formal, JCDiagnostic problem) throws InferenceException {
-        if (tvars.nonEmpty()) {
-            String errKey = problem == null ?
-                "infer.no.conforming.assignment.exists" :
-                "infer.no.conforming.assignment.exists.1";
-            throw unambiguousNoInstanceException
-                .setMessage(errKey,
-                            tvars, actual, formal, problem);
-        }
-        else {
-            String errKey = problem == null ?
-                "no.conforming.assignment.exists" :
-                "no.conforming.assignment.exists.1";
-            throw unambiguousNoInstanceException
-                .setMessage(errKey,
-                            actual, formal, problem);
-        }
-    }
-
-    private List<Type> getConstraints(List<Type> undetvars, TypeVar tv, EnumSet<ConstraintKind> constraints, List<Type> tvars, List<Type> inferred) {
-        for (Type t : undetvars) {
-            UndetVar uv = (UndetVar)t;
-            if (uv.qtype == tv) {
-                for (ConstraintKind ck : constraints) {
-                    switch (ck) {
-                        case EXTENDS:
-                            ListBuffer<Type> hibounds = ListBuffer.lb();
-                            for (Type t2 : uv.hibounds) {
-                                hibounds.appendList(t2.tag == UNDETVAR ?
-                                    getConstraints(List.of(t2), tv, EnumSet.of(ck, ConstraintKind.EQUAL), tvars, inferred) :
-                                    uv.hibounds);
-                            }
-                            return types.subst(hibounds.appendList(types.getBounds(tv)).toList(), tvars, inferred);
-                        case SUPER:
-                            ListBuffer<Type> lobounds = ListBuffer.lb();
-                            for (Type t2 : uv.lobounds) {
-                                lobounds.appendList(t2.tag == UNDETVAR ?
-                                        getConstraints(List.of(t2), tv, EnumSet.of(ck, ConstraintKind.EQUAL), tvars, inferred) :
-                                        uv.lobounds);
-                            }
-                            return types.subst(lobounds.toList(), tvars, inferred);
-                        case EQUAL: {
-                            if (uv.inst == null) return List.nil();
-                            else
-                                return uv.inst.tag == UNDETVAR ?
-                                    getConstraints(List.of(uv.inst), tv, EnumSet.of(ck), tvars, inferred) :
-                                    List.of(types.subst(uv.inst, tvars, inferred));
+                public UninferredReturnType(final Env<AttrContext> env, Type restype, final Types types) {
+                    super(POLY_RETURN, restype);
+                    completer = new Completer() {
+                        public Type complete(ForAll fa, Type to, boolean allowBoxing) {
+                            List<Type> actuals = instantiateExpr(env, fa, to, Warner.noWarnings);
+                            fa.qtype = types.subst(fa.qtype, tvars, actuals);
+                            instantiateReturnType(fa.qtype, actuals, types);
+                            return fa.qtype;
                         }
+                    };
+                    //include upper bounds
+                    for (Type t : undetVars()) {
+                        UndetVar uv = (UndetVar)t;
+                        uv.hibounds = uv.hibounds.appendList(asUndetTypes(types.getBounds((TypeVar)uv.qtype)));
                     }
                 }
             }
         }
-        return List.nil();
-    }
+    // </editor-fold>
     
-    /** Try to instantiate argument type `that' to given type `to'.
-     *  If this fails, try to insantiate `that' to `to' where
-     *  every occurrence of a type variable in `tvars' is replaced
-     *  by an unknown type.
+    // <editor-fold desc="SAM type instantiation">
+    /**
+     * This method is used to infer a suitable target SAM in case the original
+     * SAM type contains one or more wildcards. An inference process is applied
+     * so that wildcard bounds, as well as explicit lambda/method ref parameters
+     * (where applicable) are used to constraint the solution.
      */
-    public Type instantiateArg(Env<AttrContext> env, ForAll that,
-                                Type to,
-                                Warner warn, ForAll.InstantiationPhase phase) throws InferenceException {
-        Type inferredArg = null;
-        try {
-            inferredArg = instantiateExpr(env, that, to, warn, phase);
-        }
-        catch (Infer.InferenceException e) {
-            inferredArg = syms.errType;
-        }
-        return inferredArg;
-    }
-
-    /** check that type parameters are within their bounds.
-     */
-    void checkWithinBounds(List<Type> tvars,
-                                   List<Type> arguments,
-                                   Warner warn)
-        throws InvalidInstanceException {
-        for (List<Type> tvs = tvars, args = arguments;
-             tvs.nonEmpty();
-             tvs = tvs.tail, args = args.tail) {
-            if (args.head instanceof UndetVar ||
-                    tvars.head.getUpperBound().isErroneous()) continue;
-            List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
-            if (!types.isSubtypeUnchecked(args.head, bounds, warn))
-                throw invalidInstanceException
-                    .setMessage("inferred.do.not.conform.to.bounds",
-                                args.head, bounds);
+    public Type inferSAM(Env<AttrContext> env, Type samType, List<Type> paramTypes) {
+        if (types.capture(samType) == samType) {
+            //if capture doesn't change the type then return the target unchanged
+            //(this means the target contains no wilddcards!)
+            return samType;
+        } else {
+            List<Type> tvars = samType.tsym.type.getTypeArguments();
+            Type formalSam = samType.tsym.type;
+            if (paramTypes != null) {
+                pushContext(formalSam.getTypeArguments());
+                //get constraints from explicit params (this is done by
+                //checking that explicit param types are equal to the ones
+                //in the SAM descriptors)
+                Type undetSAM = asUndetType(formalSam);
+                Type target = types.findSAM(undetSAM, env).getTargetType();
+                if (!types.isSameTypes(target.getParameterTypes(), paramTypes)) {
+                    throw invalidInstanceException;
+                }
+                for (List<Type> l = undetVars(); l.nonEmpty(); l = l.tail) {
+                    UndetVar uv = (UndetVar) l.head;
+                    if (uv.lobounds.nonEmpty())
+                        minimizeInst(uv, Warner.noWarnings);
+                    else if (uv.hibounds.nonEmpty())
+                        maximizeInst(uv, Warner.noWarnings);
+                    if (uv.inst == null || uv.inst.tag == BOT) {
+                        uv.inst = uv.qtype;
+                    }
+                }
+                List<Type> targs = Type.map(undetVars(), getInstFun);
+                formalSam = types.subst(formalSam, inferenceVars(), targs);
+                //discard current context;
+                popContext(false);
+            }
+            ListBuffer<Type> typeargs = ListBuffer.lb();
+            List<Type> actualTypeargs = samType.getTypeArguments();
+            //for remaining uninferred type-vars in the SAM type,
+            //simply replace the wildcards with its bound
+            for (Type t : formalSam.getTypeArguments()) {
+                if (tvars.contains(t) && actualTypeargs.head.tag == WILDCARD) {
+                    WildcardType wt = (WildcardType)actualTypeargs.head;
+                    typeargs.append(wt.type);
+                } else {
+                    typeargs.append(t);
+                }
+                actualTypeargs = actualTypeargs.tail;
+            }
+            Type owntype = types.subst(formalSam, tvars, typeargs.toList());
+            if (!chk.checkValidGenericType(owntype) || !types.isSubtypeUnchecked(owntype, samType)) {
+                //if the inferred SAM type is not well-formed, or if it's not
+                //a subtype of the original target, issue an error
+                throw invalidInstanceException;
+            }
+            return owntype;
         }
     }
+    // </editor-fold>
 
+    // <editor-fold desc="actual argument instantiation">
+    /**
+     * Instantiate an actual argument type (whose kind is a poly type) using
+     * the corresponding formal as target type. This could trigger poly type
+     * completion (and, as a consequence, deferred attribution).
+     */
+    public Type instantiateArg(Env<AttrContext> env, Type mtype, ForAll that,
+                                Type to, Warner warn, boolean allowBoxing) throws InferenceException {
+        switch (that.getPolyTag()) {
+            case POLY_LAMBDA:
+            case POLY_REFERENCE:
+                //is the target a valid SAM?
+                Types.SAMResult samRes = types.findSAM(to, env);
+                if (samRes.isErroneous()) {
+                    throw invalidInstanceException.setMessage(samRes.getDiagnostic(diags));
+                }
+                //complete the poly type iff either (i) the lambda/mref has
+                //explicit params, or (ii) the formals in the expected SAM desc
+                //do not contain any inference var
+                List<Type> expectedFormals = samRes.getTargetType().getParameterTypes();
+                if (that.getParameterTypes() != null ||
+                         !Type.containsAny(expectedFormals, inferenceVars())) {
+                    return that.complete(asUndetType(to), allowBoxing);
+                } else {
+                    throw unambiguousNoInstanceException;
+                }
+            default: Assert.error(); return Type.noType;
+        }
+    }
+    // </editor-fold>
+
+    // <editor-fold desc="Polymorphic signature instantiation">
     /**
      * Compute a synthetic method type corresponding to the requested polymorphic
      * method signature. The target return type is computed from the immediately
@@ -798,4 +753,79 @@
                     return t;
                 }
         };
+    // </editor-fold>
+
+    // <editor-fold desc="Inference context handling">
+    /**
+     * An inference context contains a set of type-variables and corresponding
+     * undet variables, used to keep track of constraints. In the typical scenario,
+     * an inference context is pushed onto the stack when a new method signature
+     * needs to be instantiated. Such context is then popped off the stack when
+     * overload resolution is completed. It is possible that, when popping an
+     * inference context, its variables/undetvars are copied over to the
+     * outer context (this behavior is required in order to propagate inference
+     * variables in the right way).
+     */
+    class InferenceContext {
+        List<Type> tvars;
+        List<Type> undetvars;
+
+        public InferenceContext() {
+            this(List.<Type>nil());
+        }
+
+        public InferenceContext(List<Type> tvars) {
+            this.tvars = tvars;
+            this.undetvars = Type.map(tvars, fromTypeVarFun);
+        }
+
+        void clear() {
+            tvars = List.nil();
+            undetvars = List.nil();
+        }
     }
+
+    /** starts off with global context - for Check.instantiatePoly **/
+    List<InferenceContext> inferenceContexts = List.of(new InferenceContext());
+
+    void pushContext(List<Type> tvars) {
+        inferenceContexts = inferenceContexts.prepend(new InferenceContext(tvars));
+    }
+
+    void popContext(boolean merge) {
+        InferenceContext oldCtx = inferenceContexts.head;
+        inferenceContexts = inferenceContexts.tail;
+        if (merge) {
+            inferenceContexts.head.tvars = inferenceContexts.head.tvars.appendList(oldCtx.tvars);
+            inferenceContexts.head.undetvars = inferenceContexts.head.undetvars.appendList(oldCtx.undetvars);
+        }
+    }
+
+    /**
+     * Return an uninstantiated version of this type, where the inference
+     * type-variables are replaced with undetvars. This is useful in order
+     * to perform subtyping tests, conversions, etc.
+     */
+    Type asUndetType(Type t) {
+        return types.subst(t,
+                inferenceContexts.head.tvars,
+                inferenceContexts.head.undetvars);
+    }
+
+    List<Type> asUndetTypes(List<Type> ts) {
+        ListBuffer<Type> buf = ListBuffer.lb();
+        for (Type t : ts) {
+            buf.append(asUndetType(t));
+        }
+        return buf.toList();
+    }
+
+    List<Type> inferenceVars() {
+        return inferenceContexts.head.tvars;
+    }
+
+    List<Type> undetVars() {
+        return inferenceContexts.head.undetvars;
+    }
+    // </editor-fold>
+}
--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java	Fri May 20 17:19:01 2011 +0100
@@ -3140,7 +3140,7 @@
 
     @SuppressWarnings("unchecked") // XXX unchecked
     <T extends JCTree> T unlambdaIfNeeded(T tree, Type type) {
-        if (types.isSameType(tree.type, syms.methodHandleType) &&
+        if ((tree.getTag() == LAMBDA || tree.getTag() == JCTree.REFERENCE) &&
                 !types.findSAM(type, attrEnv).isErroneous()) {
             return (T)(type.isInterface() ?
                 lambdaToInterface((JCExpression)tree, type) :
@@ -4019,7 +4019,8 @@
 
     JCBlock makeLambdaBody(JCLambda tree) {
         JCReturn defaultRet = null;
-        if ((tree.sym.flags() & Flags.NEEDS_RETURN) != 0) {
+        if (tree.canCompleteNormally &&
+                types.isSameType(tree.type.getReturnType(), types.boxedClass(syms.voidType).type)) {
             defaultRet = make.Return(make.Literal(TypeTags.BOT, null).setType(syms.botType));
         }
         JCBlock body = null;
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Fri May 20 17:19:01 2011 +0100
@@ -375,11 +375,10 @@
                 exc = chk.checkClassType(l.head.pos(), exc);
             thrownbuf.append(exc);
         }
-        Type mtype = new MethodType(argbuf.toList(),
+        return new MethodType(tvars, argbuf.toList(),
                                     restype,
                                     thrownbuf.toList(),
                                     syms.methodClass);
-        return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
     }
 
 /* ********************************************************************
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri May 20 17:19:01 2011 +0100
@@ -90,12 +90,10 @@
 
         varNotFound = new
             SymbolNotFoundError(ABSENT_VAR);
-        wrongMethod = new
-            InapplicableSymbolError(syms.errSymbol);
-        wrongMethods = new
-            InapplicableSymbolsError(syms.errSymbol);
-        methodNotFound = new
-            SymbolNotFoundError(ABSENT_MTH);
+
+        methodNotFound =
+                new SymbolNotFoundError(ABSENT_MTH);
+        
         typeNotFound = new
             SymbolNotFoundError(ABSENT_TYP);
 
@@ -123,8 +121,6 @@
     /** error symbols, which are returned when resolution fails
      */
     final SymbolNotFoundError varNotFound;
-    final InapplicableSymbolError wrongMethod;
-    final InapplicableSymbolsError wrongMethods;
     final SymbolNotFoundError methodNotFound;
     final SymbolNotFoundError typeNotFound;
 
@@ -331,6 +327,7 @@
                         List<Type> typeargtypes,
                         boolean allowBoxing,
                         boolean useVarargs,
+                        boolean check,
                         Warner warn)
         throws Infer.InferenceException {
         boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles;
@@ -346,59 +343,76 @@
             mt = types.subst(mt, env.info.tvars, tvars);
         }
         if (typeargtypes == null) typeargtypes = List.nil();
-        if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
+        if (!mt.isParameterized() && typeargtypes.nonEmpty()) {
             // This is not a polymorphic method, but typeargs are supplied
             // which is fine, see JLS3 15.12.2.1
-        } else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
-            ForAll pmt = (ForAll) mt;
-            if (typeargtypes.length() != pmt.tvars.length())
+        } else if (mt.isParameterized() && typeargtypes.nonEmpty()) {
+            if (typeargtypes.length() != mt.getTypeArguments().length())
                 throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
             // Check type arguments are within bounds
-            List<Type> formals = pmt.tvars;
+            List<Type> formals = mt.getTypeArguments();
             List<Type> actuals = typeargtypes;
             ListBuffer<Type> actuals2 = ListBuffer.lb();
             while (formals.nonEmpty() && actuals.nonEmpty()) {
                 Type actual = chk.checkParameterType(actuals.head, formals.head);
                 actuals2.append(actual);
                 List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head),
-                                                pmt.tvars, typeargtypes);
+                                                mt.getTypeArguments(), typeargtypes);
                 for (; bounds.nonEmpty(); bounds = bounds.tail)
                     if (!types.isSubtypeUnchecked(actual, bounds.head, warn))
                         throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
                 formals = formals.tail;
                 actuals = actuals.tail;
             }
-            mt = types.subst(pmt.qtype, pmt.tvars, actuals2.toList());
-        } else if (mt.tag == FORALL) {
-            ForAll pmt = (ForAll) mt;
-            List<Type> tvars1 = types.newInstances(pmt.tvars);
+            Type mt2 = types.createMethodTypeWithTypeArguments((MethodType)mt, List.<Type>nil());
+            mt = types.subst(mt2, mt.getTypeArguments(), actuals2.toList());
+        } else if (mt.isParameterized()) {
+            List<Type> tvars1 = types.newInstances(mt.getTypeArguments());
             tvars = tvars.appendList(tvars1);
-            mt = types.subst(pmt.qtype, pmt.tvars, tvars1);
+            mt = types.subst(mt, mt.getTypeArguments(), tvars1);
         }
 
         // find out whether we need to go the slow route via infer
+
+        boolean hasPolyArgs = false;
+        for (Type t : argtypes) {
+            if (t.getPolyTag() != NO_POLY) {
+                hasPolyArgs = true;
+                break;
+            }
+        }
+        
         boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/
-                polymorphicSignature;
-        for (List<Type> l = argtypes;
-             l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded;
-             l = l.tail) {
-            if (l.head.tag == FORALL) instNeeded = true;
+                polymorphicSignature ||
+                hasPolyArgs;
+
+        List<Type> argsToCheck = argtypes == Type.noTypes ?
+            Type.noTypes :
+            types.capture(types.upperBounds(argtypes));
+
+        if (instNeeded) {
+            try {
+                infer.pushContext(tvars);
+                return polymorphicSignature ?
+                    infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argsToCheck) :
+                    infer.instantiateMethod(env,
+                                        tvars,
+                                        (MethodType)mt,
+                                        m,
+                                        argsToCheck,
+                                        allowBoxing,
+                                        useVarargs,
+                                        hasPolyArgs,
+                                        warn);
+            }
+            finally {
+                //if we are checking the method, and if the call is not unchecked
+                //copy current inference vars to outer inference context
+                infer.popContext(check && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED));
+            }
         }
 
-        if (instNeeded)
-            return polymorphicSignature ?
-                infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes) :
-                infer.instantiateMethod(env,
-                                    tvars,
-                                    (MethodType)mt,
-                                    m,
-                                    argtypes,
-                                    allowBoxing,
-                                    useVarargs,
-                                    warn);
-
-        checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(),
-                                allowBoxing, useVarargs, warn, ForAll.InstantiationPhase.RESOLUTION);
+        checkRawArgumentsAcceptable(env, mt, argsToCheck, allowBoxing, useVarargs, warn);
         return mt;
     }
 
@@ -411,116 +425,189 @@
                      List<Type> typeargtypes,
                      boolean allowBoxing,
                      boolean useVarargs,
+                     boolean check,
                      Warner warn) {
         try {
             return rawInstantiate(env, site, m, argtypes, typeargtypes,
-                                  allowBoxing, useVarargs, warn);
+                                  allowBoxing, useVarargs, check, warn);
         } catch (InapplicableMethodException ex) {
             return null;
         }
     }
 
+    // <editor-fold desc="method applicability check">
+
     /** Check if a parameter list accepts a list of args.
      */
     boolean argumentsAcceptable(Env<AttrContext> env,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn) {
-        return argumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn, ForAll.InstantiationPhase.CHECK);
-    }
-    boolean argumentsAcceptable(Env<AttrContext> env,
-                                List<Type> argtypes,
-                                List<Type> formals,
-                                boolean allowBoxing,
-                                boolean useVarargs,
-                                Warner warn,
-                                ForAll.InstantiationPhase phase) {
-	try {
-            checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn, phase);
+            Type mtype,
+            List<Type> argtypes,
+            boolean allowBoxing,
+            boolean useVarargs,
+            Warner warn) {
+        try {
+            checkRawArgumentsAcceptable(env, mtype, argtypes, allowBoxing, useVarargs, warn);
             return true;
         } catch (InapplicableMethodException ex) {
             return false;
         }
     }
-    void checkRawArgumentsAcceptable(Env<AttrContext> env, List<Type> argtypes,
-                                List<Type> formals,
+
+    /**
+     * A check handler is used by the main method applicability routine in order
+     * to handle specific method applicability failures. It is assumed that a class
+     * implementing this interface should throw exceptions that are a subtype of
+     * InapplicableMethodException (see below). Such exception will terminate the
+     * method applicability check and propagate important info outwards (for the
+     * purpose of generating better diagnostics).
+     */
+    interface MethodCheckHandler {
+        /* The number of actuals and formals differ */
+        void arityMismatch();
+        /* An actual argument type does not conform to the corresponding formal type */
+        void argumentMismatch(boolean varargs, Type found, Type expected, JCDiagnostic cause);
+        /* The element type of a varargs is not accessible in the current context */
+        void inaccessibleVarargs(Symbol location, Type expected);
+    }
+
+    /**
+     * Basic method check handler used within Resolve - all methods end up
+     * throwing InapplicableMethodException; a diagnostic fragment that describes
+     * the cause as to why the method is not applicable is set on the exception
+     * before it is thrown.
+     */
+    MethodCheckHandler resolveHandler = new MethodCheckHandler() {
+            public void arityMismatch() {
+                throw inapplicableMethodException.setMessage("arg.length.mismatch");
+            }
+            public void argumentMismatch(boolean varargs, Type found, Type expected, JCDiagnostic cause) {
+                String key = null;
+                if (varargs) {
+                    key = cause == null ?
+                        "varargs.argument.mismatch" :
+                        "varargs.argument.mismatch.1";
+                } else {
+                    key = cause == null ?
+                        "no.conforming.assignment.exists" :
+                        "no.conforming.assignment.exists.1";
+                }
+                throw inapplicableMethodException.setMessage(key,
+                        found, expected, cause);
+            }
+            public void inaccessibleVarargs(Symbol location, Type expected) {
+                throw inapplicableMethodException.setMessage("inaccessible.varargs.type",
+                        expected, Kinds.kindName(location), location);
+            }
+    };
+
+    List<Type> checkRawArgumentsAcceptable(Env<AttrContext> env,
+                                Type mtype,
+                                List<Type> argtypes,
+                                boolean allowBoxing,
+                                boolean useVarargs,
+                                Warner warn) {
+        return checkRawArgumentsAcceptable(env, mtype, argtypes,
+                allowBoxing, useVarargs, warn, resolveHandler);
+    }
+
+    /**
+     * Main method applicability routine. Given a list of actual types A,
+     * a list of formal types F, determines whether the types in A are
+     * compatible (by method invocation conversion) with the types in F.
+     *
+     * Since this routine is shared between overload resolution and method
+     * type-inference, it is crucial that actual types are converted to the
+     * corresponding 'undet' form (i.e. where inference variables are replaced
+     * with undetvars) so that constraints can be propagated and collected.
+     *
+     * Moreover, if one or more types in A is a poly type, this routine calls
+     * Infer.instantiateArg in order to complete the poly type (this might involve
+     * deferred attribution).
+     *
+     * A method check handler (see above) is used in order to report errors.
+     */
+    List<Type> checkRawArgumentsAcceptable(Env<AttrContext> env,
+                                Type mtype,
+                                List<Type> argtypes,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn,
-                                ForAll.InstantiationPhase phase) {
-        if (argtypes == Type.noTypes) return;
+                                MethodCheckHandler handler) {
+        if (argtypes == Type.noTypes) return List.nil();
+        
+        List<Type> formals = mtype.getParameterTypes();
         Type varargsFormal = useVarargs ? formals.last() : null;
+        List<Type> uncheckedArgs = List.nil();
+        
         if (varargsFormal == null &&
                 argtypes.size() != formals.size()) {
-            throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
+            handler.arityMismatch(); // not enough args
+            return uncheckedArgs;
         }
 
         while (argtypes.nonEmpty() && formals.head != varargsFormal) {
-            Type actual = argtypes.head.tag == FORALL ?
-                infer.instantiateArg(env, (ForAll)argtypes.head, formals.head, warn, phase) :
-                argtypes.head;
-            boolean works = false;
-            JCDiagnostic problem = null;
-            try {
-                works = chk.checkArgument(env, actual, formals.head, allowBoxing, warn);
-            }
-            catch (Types.ConversionException ex) {
-                problem = ex.getDiagnostic(diags);
-            }
-            if (!works) {
-                String errKey = problem == null ?
-                    "no.conforming.assignment.exists" :
-                    "no.conforming.assignment.exists.1";
-                throw inapplicableMethodException.setMessage(errKey,
-                        actual,
-                        formals.head, problem);
+            Type actual = argtypes.head;
+            if (actual.tag == FORALL) {
+                try {
+                    infer.instantiateArg(env, mtype, (ForAll)actual, formals.head, warn, allowBoxing);
+                } catch (Infer.NoInstanceException ex) {
+                    uncheckedArgs = uncheckedArgs.append(actual);
+                } catch (Infer.InvalidInstanceException ex) {
+                    handler.argumentMismatch(useVarargs, actual, formals.head, ex.diagnostic);
+                }
+            } else {
+                Type undetFormal = infer.asUndetType(formals.head);
+                boolean works = allowBoxing ?
+                        types.isConvertible(argtypes.head, undetFormal, warn) :
+                        types.isSubtypeUnchecked(argtypes.head, undetFormal, warn);
+                if (!works) {
+                    handler.argumentMismatch(false, argtypes.head, formals.head, null);
+                    return null;
+                }
             }
             argtypes = argtypes.tail;
             formals = formals.tail;
         }
 
-        if (formals.head != varargsFormal)
-            throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
+        if (formals.head != varargsFormal) {
+            handler.arityMismatch(); // not enough args
+            return uncheckedArgs;
+        }
 
         if (useVarargs) {
             //note: if applicability check is triggered by most specific test,
             //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
             Type elt = types.elemtypeOrType(varargsFormal);
     	    while (argtypes.nonEmpty()) {
-    	        Type actual = argtypes.head.tag == FORALL ?
-    	            infer.instantiateArg(env, (ForAll)argtypes.head, elt, warn, phase) :
-                    argtypes.head;
-                boolean works = false;
-                JCDiagnostic problem = null;
-                try {
-                    works = chk.checkArgument(env, actual, elt, allowBoxing, warn);
-                }
-                catch (Types.ConversionException ex) {
-                    problem = ex.getDiagnostic(diags);
-                }
-    	        if (!works) {
-                    String errKey = problem == null ?
-                        "varargs.argument.mismatch" :
-                        "varargs.argument.mismatch.1";
-    	            throw inapplicableMethodException.setMessage(errKey,
-                            actual,
-                            elt,
-                            problem);
+                Type actual = argtypes.head;
+                if (actual.tag == FORALL) {
+                    try {
+                        infer.instantiateArg(env, mtype, (ForAll)actual, elt, warn, allowBoxing);
+                    } catch (Infer.NoInstanceException ex) {
+                        uncheckedArgs = uncheckedArgs.append(actual);
+                    } catch (InapplicableMethodException ex) {
+                        handler.argumentMismatch(true, actual, elt, ex.diagnostic);
+                    }
+                } else {
+                    Type eltUndet = infer.asUndetType(elt);
+                    if (!types.isConvertible(actual, eltUndet, warn)) {
+                        handler.argumentMismatch(true,
+                                argtypes.head,
+                                elt, null);
+                        return uncheckedArgs;
+                    }
                 }
     	        argtypes = argtypes.tail;
     	    }
             //check varargs element type accessibility
             if (!isAccessible(env, elt)) {
                 Symbol location = env.enclClass.sym;
-                throw inapplicableMethodException.setMessage("inaccessible.varargs.type",
-                            elt,
-                            Kinds.kindName(location),
-                            location);
+                handler.inaccessibleVarargs(location, elt);
             }
         }
+        return uncheckedArgs;
     }
+
     // where
         public static class InapplicableMethodException extends RuntimeException {
             private static final long serialVersionUID = 0;
@@ -554,6 +641,7 @@
             }
         }
         private final InapplicableMethodException inapplicableMethodException;
+    // </editor-fold>
 
 /* ***************************************************************************
  *  Symbol lookup
@@ -729,15 +817,15 @@
         Assert.check(sym.kind < AMBIGUOUS);
         try {
             rawInstantiate(env, site, sym, argtypes, typeargtypes,
-                               allowBoxing, useVarargs, Warner.noWarnings);
+                               allowBoxing, useVarargs, false, Warner.noWarnings);
         } catch (InapplicableMethodException ex) {
             switch (bestSoFar.kind) {
             case ABSENT_MTH:
-                return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
+                return currentResolutionContext.wrongMethod.setWrongSym(sym, ex.getDiagnostic());
             case WRONG_MTH:
-                wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
+                currentResolutionContext.wrongMethods.addInitialCandidate();
             case WRONG_MTHS:
-                return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
+                return currentResolutionContext.wrongMethods.addCandidate(sym, ex.getDiagnostic());
             default:
                 return bestSoFar;
             }
@@ -813,8 +901,8 @@
                 // both abstract, neither overridden; merge throws clause and result type
                 Symbol mostSpecific;
                 Type result2 = mt2.getReturnType();
-                if (mt2.tag == FORALL)
-                    result2 = types.subst(result2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
+                if (mt2.isParameterized())
+                    result2 = types.subst(result2, mt2.getTypeArguments(), mt1.getTypeArguments());
                 if (types.isSubtype(mt1.getReturnType(), result2))
                     mostSpecific = m1;
                 else if (types.isSubtype(result2, mt1.getReturnType()))
@@ -865,9 +953,9 @@
         noteWarner.clear();
         Type mtype1 = types.memberType(site, adjustVarargs(m1, m2, useVarargs));
         return (instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
-                             allowBoxing, false, noteWarner) != null ||
+                             allowBoxing, false, false, noteWarner) != null ||
                  useVarargs && instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
-                                           allowBoxing, true, noteWarner) != null) &&
+                                           allowBoxing, true, false, noteWarner) != null) &&
                 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
     }
     //where
@@ -1481,32 +1569,33 @@
                          Name name,
                          List<Type> argtypes,
                          List<Type> typeargtypes) {
-        Symbol sym = startResolution();
-        List<MethodResolutionPhase> steps = methodResolutionSteps;
-        while (steps.nonEmpty() &&
-               steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
-               sym.kind >= ERRONEOUS) {
-            currentStep = steps.head;
-            sym = findFun(env, name, argtypes, typeargtypes,
-                    steps.head.isBoxingRequired,
-                    env.info.varArgs = steps.head.isVarargsRequired);
-            methodResolutionCache.put(steps.head, sym);
-            steps = steps.tail;
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= ERRONEOUS) {
+                currentResolutionContext.step = steps.head;
+                sym = findFun(env, name, argtypes, typeargtypes,
+                        steps.head.isBoxingRequired,
+                        env.info.varArgs = steps.head.isVarargsRequired);
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
+                MethodResolutionPhase errPhase =
+                        currentResolutionContext.firstErroneousResolutionPhase();
+                sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+                        pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
+                env.info.varArgs = errPhase.isVarargsRequired;
+            }
+            return sym;
         }
-        if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
-            MethodResolutionPhase errPhase =
-                    firstErroneousResolutionPhase();
-            sym = access(methodResolutionCache.get(errPhase),
-                    pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
-            env.info.varArgs = errPhase.isVarargsRequired;
+        finally {
+            currentResolutionContext = prevResolutionContext;
         }
-        return sym;
-    }
-
-    private Symbol startResolution() {
-        wrongMethod.clear();
-        wrongMethods.clear();
-        return methodNotFound;
     }
 
     /** Resolve a qualified method identifier
@@ -1526,40 +1615,47 @@
     Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
                                   Symbol location, Type site, Name name, List<Type> argtypes,
                                   List<Type> typeargtypes) {
-        Symbol sym = startResolution();
-        List<MethodResolutionPhase> steps = methodResolutionSteps;
-        while (steps.nonEmpty() &&
-               steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
-               sym.kind >= ERRONEOUS) {
-            currentStep = steps.head;
-            sym = findMethod(env, site, name, argtypes, typeargtypes,
-                    steps.head.isBoxingRequired(),
-                    env.info.varArgs = steps.head.isVarargsRequired(), false);
-            methodResolutionCache.put(steps.head, sym);
-            steps = steps.tail;
-        }
-        if (sym.kind >= AMBIGUOUS) {
-            if (site.tsym.isPolymorphicSignatureGeneric()) {
-                //polymorphic receiver - synthesize new method symbol
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= ERRONEOUS) {
+                currentResolutionContext.step = steps.head;
+                sym = findMethod(env, site, name, argtypes, typeargtypes,
+                        steps.head.isBoxingRequired(),
+                        env.info.varArgs = steps.head.isVarargsRequired(), false);
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            if (sym.kind >= AMBIGUOUS) {
+                if (site.tsym.isPolymorphicSignatureGeneric()) {
+                    //polymorphic receiver - synthesize new method symbol
+                    env.info.varArgs = false;
+                    sym = findPolymorphicSignatureInstance(env,
+                            site, name, null, argtypes);
+                }
+                else {
+                    //if nothing is found return the 'first' error
+                    MethodResolutionPhase errPhase =
+                            currentResolutionContext.firstErroneousResolutionPhase();
+                    sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+                            pos, location, site, name, true, argtypes, typeargtypes);
+                    env.info.varArgs = errPhase.isVarargsRequired;
+                }
+            } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
+                //non-instantiated polymorphic signature - synthesize new method symbol
                 env.info.varArgs = false;
                 sym = findPolymorphicSignatureInstance(env,
-                        site, name, null, argtypes);
+                        site, name, (MethodSymbol)sym, argtypes);
             }
-            else {
-                //if nothing is found return the 'first' error
-                MethodResolutionPhase errPhase =
-                        firstErroneousResolutionPhase();
-                sym = access(methodResolutionCache.get(errPhase),
-                        pos, location, site, name, true, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired;
-            }
-        } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
-            //non-instantiated polymorphic signature - synthesize new method symbol
-            env.info.varArgs = false;
-            sym = findPolymorphicSignatureInstance(env,
-                    site, name, (MethodSymbol)sym, argtypes);
+            return sym;
         }
-        return sym;
+        finally {
+            currentResolutionContext = prevResolutionContext;
+        }
     }
 
     /** Find or create an implicit method of exactly the given type (after erasure).
@@ -1638,25 +1734,32 @@
                               Type site,
                               List<Type> argtypes,
                               List<Type> typeargtypes) {
-        Symbol sym = startResolution();
-        List<MethodResolutionPhase> steps = methodResolutionSteps;
-        while (steps.nonEmpty() &&
-               steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
-               sym.kind >= ERRONEOUS) {
-            currentStep = steps.head;
-            sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
-                    steps.head.isBoxingRequired(),
-                    env.info.varArgs = steps.head.isVarargsRequired());
-            methodResolutionCache.put(steps.head, sym);
-            steps = steps.tail;
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= ERRONEOUS) {
+                currentResolutionContext.step = steps.head;
+                sym = findConstructor(pos, env, site, argtypes, typeargtypes,
+                        steps.head.isBoxingRequired(),
+                        env.info.varArgs = steps.head.isVarargsRequired());
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
+                MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+                sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+                        pos, site, names.init, true, argtypes, typeargtypes);
+                env.info.varArgs = errPhase.isVarargsRequired();
+            }
+            return sym;
         }
-        if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
-            MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
-            sym = access(methodResolutionCache.get(errPhase),
-                    pos, site, names.init, true, argtypes, typeargtypes);
-            env.info.varArgs = errPhase.isVarargsRequired();
+        finally {
+            currentResolutionContext = prevResolutionContext;
         }
-        return sym;
     }
 
     /** Resolve constructor using diamond inference.
@@ -1674,38 +1777,45 @@
                               Type site,
                               List<Type> argtypes,
                               List<Type> typeargtypes) {
-        Symbol sym = startResolution();
-        List<MethodResolutionPhase> steps = methodResolutionSteps;
-        while (steps.nonEmpty() &&
-               steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
-               sym.kind >= ERRONEOUS) {
-            currentStep = steps.head;
-            sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
-                    steps.head.isBoxingRequired(),
-                    env.info.varArgs = steps.head.isVarargsRequired());
-            methodResolutionCache.put(steps.head, sym);
-            steps = steps.tail;
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= ERRONEOUS) {
+                currentResolutionContext.step = steps.head;
+                sym = findConstructor(pos, env, site, argtypes, typeargtypes,
+                        steps.head.isBoxingRequired(),
+                        env.info.varArgs = steps.head.isVarargsRequired());
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            if (sym.kind >= AMBIGUOUS) {
+                final JCDiagnostic details = sym.kind == WRONG_MTH ?
+                    ((InapplicableSymbolError)sym).explanation :
+                    null;
+                Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
+                    @Override
+                    JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
+                            Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+                        String key = details == null ?
+                            "cant.apply.diamond" :
+                            "cant.apply.diamond.1";
+                        return diags.create(dkind, log.currentSource(), pos, key,
+                                diags.fragment("diamond", site.tsym), details);
+                    }
+                };
+                MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+                sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
+                env.info.varArgs = errPhase.isVarargsRequired();
+            }
+            return sym;
         }
-        if (sym.kind >= AMBIGUOUS) {
-            final JCDiagnostic details = sym.kind == WRONG_MTH ?
-                ((InapplicableSymbolError)sym).explanation :
-                null;
-            Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
-                @Override
-                JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
-                        Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
-                    String key = details == null ?
-                        "cant.apply.diamond" :
-                        "cant.apply.diamond.1";
-                    return diags.create(dkind, log.currentSource(), pos, key,
-                            diags.fragment("diamond", site.tsym), details);
-                }
-            };
-            MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
-            sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
-            env.info.varArgs = errPhase.isVarargsRequired();
+        finally {
+            currentResolutionContext = prevResolutionContext;
         }
-        return sym;
     }
 
     /** Resolve constructor.
@@ -1724,6 +1834,25 @@
                               List<Type> typeargtypes,
                               boolean allowBoxing,
                               boolean useVarargs) {
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = findConstructor(pos, env, site,
+                                    argtypes,
+                                    typeargtypes, allowBoxing,
+                                    useVarargs);
+            return sym;
+        }
+        finally {
+            currentResolutionContext = prevResolutionContext;
+        }
+    }
+
+    Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
+                              Type site, List<Type> argtypes,
+                              List<Type> typeargtypes,
+                              boolean allowBoxing,
+                              boolean useVarargs) {
         Symbol sym = findMethod(env, site,
                                 names.init, argtypes,
                                 typeargtypes, allowBoxing,
@@ -1758,14 +1887,21 @@
      */
     Symbol resolveOperator(DiagnosticPosition pos, int optag,
                            Env<AttrContext> env, List<Type> argtypes) {
-        Name name = treeinfo.operatorName(optag);
-        Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
-                                null, false, false, true);
-        if (boxingEnabled && sym.kind >= WRONG_MTHS)
-            sym = findMethod(env, syms.predefClass.type, name, argtypes,
-                             null, true, false, true);
-        return access(sym, pos, env.enclClass.sym.type, name,
-                      false, argtypes, null);
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Name name = treeinfo.operatorName(optag);
+            Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
+                                    null, false, false, true);
+            if (boxingEnabled && sym.kind >= WRONG_MTHS)
+                sym = findMethod(env, syms.predefClass.type, name, argtypes,
+                                 null, true, false, true);
+            return access(sym, pos, env.enclClass.sym.type, name,
+                          false, argtypes, null);
+        }
+        finally {
+            currentResolutionContext = prevResolutionContext;
+        }
     }
 
     /** Resolve operator.
@@ -2045,12 +2181,6 @@
             if (name == names.error)
                 return null;
 
-            if (name == names.empty &&
-                    !types.isFunctionType(site)) {
-                return diags.create(dkind, log.currentSource(), pos,
-                        "lambda.call.non.func.type", site);
-            }
-
             if (isOperator(name)) {
                 boolean isUnaryOp = argtypes.size() == 1;
                 String key = argtypes.size() == 1 ?
@@ -2174,13 +2304,6 @@
                 return diags.create(dkind, log.currentSource(), pos,
                         key, name, first, second);
             }
-            else if (types.isFunctionType(site) &&
-                    name == names.empty) {
-                return diags.create(dkind, log.currentSource(), pos,
-                          "cant.apply.lambda",
-                          methodArguments(site.getParameterTypes()),
-                          methodArguments(argtypes));
-            }
             else {
                 Symbol ws = sym.asMemberOf(site, types);
                 return diags.create(dkind, log.currentSource(), pos,
@@ -2249,13 +2372,18 @@
             return details.reverse();
         }
 
-        Symbol addCandidate(MethodResolutionPhase currentStep, Symbol sym, JCDiagnostic details) {
-            Candidate c = new Candidate(currentStep, sym, details);
+        Symbol addCandidate(Symbol sym, JCDiagnostic details) {
+            Candidate c = new Candidate(currentResolutionContext.step, sym, details);
             if (c.isValid() && !candidates.contains(c))
                 candidates = candidates.append(c);
             return this;
         }
 
+        Symbol addInitialCandidate() {
+            return addCandidate(currentResolutionContext.wrongMethod.sym,
+                    currentResolutionContext.wrongMethod.explanation);
+        }
+
         void clear() {
             candidates = List.nil();
         }
@@ -2467,24 +2595,41 @@
         }
     }
 
-    private Map<MethodResolutionPhase, Symbol> methodResolutionCache =
-        new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
-
     final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
 
-    private MethodResolutionPhase currentStep = null;
+    /**
+     * A resolution context is used to keep track of intermediate results of
+     * overload resolution, such as list of method that are not applicable
+     * (used to generate more precise diagnostics) and so on. Resolution contexts
+     * can be nested, in case overload resolution trigers deferred attribution
+     * (i.e. of the body of a lambda expression). This means that when overload
+     * resolution begins, a new context should be created and prepended to the
+     * list of pending resolution contexts.
+     */
+    class MethodResolutionContext {
+        
+        final InapplicableSymbolError wrongMethod = new InapplicableSymbolError(syms.errSymbol);
+        final InapplicableSymbolsError wrongMethods = new InapplicableSymbolsError(syms.errSymbol);
 
-    private MethodResolutionPhase firstErroneousResolutionPhase() {
-        MethodResolutionPhase bestSoFar = BASIC;
-        Symbol sym = methodNotFound;
-        List<MethodResolutionPhase> steps = methodResolutionSteps;
-        while (steps.nonEmpty() &&
-               steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
-               sym.kind >= WRONG_MTHS) {
-            sym = methodResolutionCache.get(steps.head);
-            bestSoFar = steps.head;
-            steps = steps.tail;
+        private Map<MethodResolutionPhase, Symbol> resolutionCache =
+            new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
+
+        private MethodResolutionPhase step = null;
+
+        private MethodResolutionPhase firstErroneousResolutionPhase() {
+            MethodResolutionPhase bestSoFar = BASIC;
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= WRONG_MTHS) {
+                sym = resolutionCache.get(steps.head);
+                bestSoFar = steps.head;
+                steps = steps.tail;
+            }
+            return bestSoFar;
         }
-        return bestSoFar;
     }
+
+    MethodResolutionContext currentResolutionContext = null;
 }
--- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri May 20 17:19:01 2011 +0100
@@ -123,7 +123,7 @@
     JCExpression coerce(JCExpression tree, Type target) {
         Type btarget = target.baseType();
         if (tree.type.isPrimitive() == target.isPrimitive()) {
-            return types.isAssignableNoCheck(tree.type, btarget, Warner.noWarnings)
+            return types.isAssignable(tree.type, btarget, Warner.noWarnings)
                 ? tree
                 : cast(tree, btarget);
         }
@@ -529,6 +529,7 @@
         try {
             currentMethod = tree.sym;
             pt = null;
+            tree.type = erasure(tree.type);
             super.visitLambda(tree);
         }
         finally {
@@ -764,7 +765,7 @@
 
     public void visitReference(JCMemberReference tree) {
         tree.expr = translate(tree.expr, null);
-        tree.type = types.erasure(tree.type);
+        tree.type = syms.methodHandleType;
         result = tree;
     }
 
@@ -780,11 +781,6 @@
         JCTree clazz = translate(tree.clazz, null);
         result = clazz;
     }
-
-    @Override
-    public void visitFunctionType(JCFunctionType that) {
-        result = make.QualIdent(syms.methodHandleType.tsym).setType(syms.methodHandleType).setPos(that.pos);
-    }
     
 /**************************************************************************
  * utility methods
--- a/src/share/classes/com/sun/tools/javac/comp/Unlambda.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Unlambda.java	Fri May 20 17:19:01 2011 +0100
@@ -93,30 +93,13 @@
 
     @Override
     public void visitLambda(JCLambda tree) {
-        if (types.isFunctionType(tree.targetType)) {
-            //lambda expression whose target is a function type are still
-            //translated in Lower
-            result = tree;
-            return;
-        }
-
-        Type type = tree.targetType;
-
         //create new anon class definition implementing SAM method
         //   class <anon> extends SAMClass { ... }
 
         ClassSymbol samClassSym = (ClassSymbol)tree.sym.owner;
+        Type targetType = ((ForAll)tree.type).qtype;
 
-        //add this
-//        VarSymbol thisSym = new VarSymbol(Flags.FINAL | Flags.HASINIT,
-//                    names._this,
-//                    samClassSym.type,
-//                    samClassSym);
-//        samClassSym.members().enter(thisSym);
-
-        Type superType = types.isFunctionType(tree.targetType) ?
-            syms.methodHandleType :
-            tree.targetType;
+        Type superType = targetType;
 
         if (superType.isInterface()) {
             ((ClassType)samClassSym.type).supertype_field = syms.objectType;
@@ -130,8 +113,8 @@
                 make.Modifiers(samClassSym.flags_field),
                 names.empty,
                 List.<JCTypeParameter>nil(),
-                type.isInterface() ? make.QualIdent(syms.objectType.tsym).setType(syms.objectType) : make.QualIdent(type.tsym).setType(type),
-                type.isInterface() ? List.of(make.QualIdent(type.tsym).setType(type)) : List.<JCExpression>nil(),
+                targetType.isInterface() ? make.QualIdent(syms.objectType.tsym).setType(syms.objectType) : make.QualIdent(targetType.tsym).setType(targetType),
+                targetType.isInterface() ? List.of(make.QualIdent(targetType.tsym).setType(targetType)) : List.<JCExpression>nil(),
                 null);
 
         samClassDecl.sym = samClassSym;
@@ -157,7 +140,7 @@
 
         JCNewClass newClass = make.NewClass(null,
                 List.<JCExpression>nil(),
-                make.QualIdent(type.tsym),
+                make.QualIdent(targetType.tsym),
                 List.<JCExpression>nil(),
                 samClassDecl);
         newClass.constructor = samConstrDecl.sym;
@@ -204,7 +187,11 @@
 
     JCBlock makeLambdaBody(JCLambda tree) {
         JCReturn defaultRet = null;
-        if ((tree.sym.flags() & Flags.NEEDS_RETURN) != 0) {
+        if (tree.canCompleteNormally &&
+                types.isSameType(tree.sym.type.getReturnType(), types.boxedClass(syms.voidType).type)) {
+            //there's no return statement and the lambda (possibly inferred)
+            //return type is java.lang.Void; sets the NEEDS_RETURN flag in
+            //order to tell code generation to emit a synthetic return statement
             defaultRet = make.Return(make.Literal(TypeTags.BOT, null).setType(syms.botType));
         }
         JCBlock body = null;
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri May 20 17:19:01 2011 +0100
@@ -686,9 +686,12 @@
                                   syms.methodClass);
         case '<':
             typevars = typevars.dup(currentOwner);
-            Type poly = new ForAll(sigToTypeParams(), sigToType());
+            List<Type> tvars = sigToTypeParams();
+            Type mt = sigToType();
+            Assert.check(mt.tag == METHOD);
+            ((MethodType)mt).typeargs = tvars;
             typevars = typevars.leave();
-            return poly;
+            return mt;
         default:
             throw badClassFile("bad.signature",
                                Convert.utf2string(signature, sigp, 10));
@@ -982,7 +985,7 @@
                     for (int j = 0; j < nexceptions; j++)
                         thrown = thrown.prepend(readClassSymbol(nextChar()).type);
                     if (sym.type.getThrownTypes().isEmpty())
-                        sym.type.asMethodType(types).thrown = thrown.reverse();
+                        sym.type.asMethodType().thrown = thrown.reverse();
                 }
             },
 
@@ -1081,7 +1084,7 @@
                         sym.type = readType(nextChar());
                         //- System.err.println(" # " + sym.type);
                         if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
-                            sym.type.asMethodType(types).thrown = thrown;
+                            sym.type.asMethodType().thrown = thrown;
 
                     }
                 }
@@ -1242,10 +1245,10 @@
         if (nt == null)
             return null;
 
-        MethodType type = nt.type.asMethodType(types);
+        MethodType type = nt.type.asMethodType();
 
         for (Scope.Entry e = scope.lookup(nt.name); e.scope != null; e = e.next())
-            if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(types), type))
+            if (e.sym.kind == MTH && isSameBinaryType(e.sym.type.asMethodType(), type))
                 return (MethodSymbol)e.sym;
 
         if (nt.name != names.init)
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri May 20 17:19:01 2011 +0100
@@ -307,6 +307,9 @@
             break;
         case METHOD:
             MethodType mt = (MethodType)type;
+            if (mt.isParameterized()) {
+                assembleParamsSig(mt.getTypeArguments());
+            }
             sigbuf.appendByte('(');
             assembleSig(mt.argtypes);
             sigbuf.appendByte(')');
@@ -342,11 +345,6 @@
             sigbuf.appendName(type.tsym.name);
             sigbuf.appendByte(';');
             break;
-        case FORALL:
-            ForAll ft = (ForAll)type;
-            assembleParamsSig(ft.tvars);
-            assembleSig(ft.qtype);
-            break;
         case DISJOINT:
             DisjunctiveType dt = (DisjunctiveType)type;
             sigbuf.appendByte('|');
--- a/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Fri May 20 17:19:01 2011 +0100
@@ -97,7 +97,7 @@
     public boolean isAssignable(TypeMirror t1, TypeMirror t2) {
         validateTypeNotIn(t1, EXEC_OR_PKG);
         validateTypeNotIn(t2, EXEC_OR_PKG);
-        return types.isAssignableNoCheck((Type) t1, (Type) t2, Warner.noWarnings);
+        return types.isAssignable((Type) t1, (Type) t2, Warner.noWarnings);
     }
     
     public boolean contains(TypeMirror t1, TypeMirror t2) {
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri May 20 17:19:01 2011 +0100
@@ -104,8 +104,6 @@
         this.allowDefenderMethods = source.allowDefenderMethods();
         this.allowThrowTypeParameters = source.allowThrowTypeParameters();
         this.allowLambda = source.allowLambda();
-        this.allowFunctionTypes = source.allowLambda() && false && //disabled!!!
-                fac.options.get("allowFunctionTypes") != null;
         this.keepDocComments = keepDocComments;
         if (keepDocComments)
             docComments = new HashMap<JCTree,String>();
@@ -162,10 +160,6 @@
      */
     boolean allowLambda;
 
-    /** Switch: should we recognize function types?
-     */
-    boolean allowFunctionTypes;
-
     /** Switch: should we recognize throw type-parameters?
      */
     boolean allowThrowTypeParameters;
@@ -1347,26 +1341,6 @@
         return toP(F.at(pos).Lambda(args, expr));
     }
 
-    JCExpression functionType() {
-        mode = TYPE;
-        checkFunctionTypes();
-        JCExpression retType = parseType();
-        accept(LPAREN);
-        List<JCExpression> args = (S.token() == RPAREN) ?
-            List.<JCExpression>nil() :
-            typeList();
-        accept(RPAREN);
-        List<JCExpression> thrown = List.nil();
-        if (S.token() == LPAREN &&
-                S.peekToken() == THROWS) {
-            S.nextToken();
-                accept(THROWS);
-                thrown = qualidentList();
-                accept(RPAREN);
-        }
-        return toP(F.at(S.pos()).FunctionType(args, retType, thrown));
-    }
-
     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
      *              | MemberReferenceSuffix
      */
@@ -3430,12 +3404,6 @@
             allowLambda = true;
         }
     }
-    void checkFunctionTypes() {
-        if (!allowFunctionTypes) {
-            log.error(S.pos(), "func.types.not.supported.in.source", source.name);
-            allowFunctionTypes = true;
-        }
-    }
     void checkThrowTypeParameters() {
         if (!allowThrowTypeParameters) {
             log.error(S.pos(), "throw.typarams.not.supported.in.source", source.name);
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri May 20 17:19:01 2011 +0100
@@ -162,18 +162,8 @@
 compiler.err.cant.apply.symbols=\
     no suitable {0} found for {1}({2})
 
-compiler.err.cant.apply.lambda=\
-    lambda expression cannot be applied to given types\n\
-    required: {0}\n\
-    found: {1}
-
-compiler.warn.cyclic.lambda.inference.throws=\
-    thrown types cannot be inferred from lambda body because of cyclic inference\n\
-    explicit type required for the following parameter: {0}
-
-compiler.warn.cyclic.lambda.inference.throws.1=\
-    thrown types cannot be inferred from lambda body because of cyclic inference\n\
-    explicit types required for the following parameters: {0}
+compiler.misc.cyclic.lambda.inference=\
+    cyclic inference - try specifying lambda parameter types
 
 compiler.err.invalid.target.type.for.lambda.conv=\
     invalid target type {0} for lambda conversion
@@ -185,9 +175,6 @@
 compiler.misc.no.target.method.for.lambda.conv=\
     no target method for lambda conversion found in {1} {2}
 
-compiler.misc.incompatible.target.in.lambda.conv=\
-    target method {0} in {1} {2} is not suitable for lambda conversion
-
 compiler.misc.incompatible.targets.in.lambda.conv=\
     no suitable target method for lambda conversion found in {1} {2}
 
@@ -212,6 +199,9 @@
 compiler.misc.multiple.targets.for.lambda.conv=\
     the target type of a lambda conversion has multiple non-overriding abstract methods
 
+compiler.misc.no.suitable.sam.inst=\
+    no instance of type {0} exists so that lambda expression can be type-checked
+
 # 0: symbol
 compiler.err.cant.assign.val.to.final.var=\
     cannot assign a value to final variable {0}
@@ -620,10 +610,14 @@
     second operand: {0}\n\
     third operand : {1}
 
-compiler.err.incompatibles.ret.types.in.lambda=\
-incompatible return types in lambda expression: neither is a subtype of the other\n\
-expected type: {0}\n\
-found : {1}
+compiler.misc.infer.incompatible.ret.types.in.lambda=\
+    incompatible return type {0} in lambda expression
+
+compiler.misc.infer.incompatible.thrown.types.in.lambda=\
+    incompatible thrown types {0} in lambda expression
+
+compiler.misc.infer.incompatible.arg.types.in.lambda=\
+    incompatible parameter types in lambda expression
 
 compiler.err.new.not.allowed.in.annotation=\
     ''new'' not allowed in an annotation
@@ -1719,6 +1713,13 @@
     no instance(s) of type variable(s) {0} exist so that argument type {1} conforms to formal parameter type {2}\n\
     ({3})
 
+compiler.misc.infer.varargs.argument.mismatch=\
+    no instance(s) of type variable(s) {0} exists so that argument type {1} does not conform to vararg element type {2}
+
+compiler.misc.infer.varargs.argument.mismatch.1=\
+    no instance(s) of type variable(s) {0} exists so that argument type {1} does not conform to vararg element type {2}\n\
+    ({3})
+
 compiler.misc.infer.arg.length.mismatch=\
     cannot instantiate from arguments because actual and formal argument lists differ in length
 
@@ -1822,10 +1823,6 @@
     symbol:   {0} <{2}>{1}({3})\n\
     location: {4}
 
-
-compiler.err.lambda.call.non.func.type=\
-    lambda invocation syntax cannot be used on non-lambda type {0}
-
 ##a location subdiagnostic is composed as follows:
 ## The first argument {0} is the location "kindname" (e.g. 'constructor', 'field', etc.)
 ## The second argument {1} is the location name
@@ -2060,10 +2057,6 @@
     lambda expressions are not supported in -source {0}\n\
     (use -source 8 or higher to enable lambda expressions)
 
-compiler.err.func.types.not.supported.in.source=\
-    function types are not supported in -source {0}\n\
-    (use -source 8 or higher and -XDallowFunctionTypes to enable function types)
-
 compiler.err.defender.methods.not.supported.in.source=\
     defender methods are not supported in -source {0}\n\
     (use -source 8 or higher to enable defender methods)
@@ -2087,6 +2080,9 @@
 compiler.misc.type.lambda=\
     <lambda>
 
+compiler.misc.type.mref=\
+    <method-ref>
+
 # X#n (where n is an int id) is disambiguated tvar name
 # 0: name, 1: number
 compiler.misc.type.var=\
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Fri May 20 17:19:01 2011 +0100
@@ -249,13 +249,9 @@
      */
     public static final int TYPEDISJUNCTION = TYPEAPPLY + 1;
 
-    /** Function types, of type FunctionType.
-     */
-    public static final int TYPEFUNCTION = TYPEDISJUNCTION + 1;
-
     /** Formal type parameters, of type TypeParameter.
      */
-    public static final int TYPEPARAMETER = TYPEFUNCTION + 1;
+    public static final int TYPEPARAMETER = TYPEDISJUNCTION + 1;
 
     /** Type argument.
      */
@@ -1466,7 +1462,8 @@
         public List<JCVariableDecl> params;
         public JCTree body;
         public Symbol sym;
-        public Type targetType;
+        public boolean canCompleteNormally = true;
+        public List<Type> inferredThrownTypes;
         
         private boolean needsParameterInference = false;
     
@@ -2032,49 +2029,6 @@
         }
     }
 
-    /** A function type.
-     * @param argumentTypes the types of the function arguments.
-     * @param resultType the type of the result of the function.
-     * @param thrown the list of checked excpetions thrown by the function.
-     */
-    public static class JCFunctionType extends JCExpression implements FunctionTypeTree {
-        public List<JCExpression> argumentTypes;
-        public JCExpression resultType;
-        public List<JCExpression> thrown;
-
-        public JCFunctionType(List<JCExpression> argumentTypes,
-                          JCExpression resultType,
-                          List<JCExpression> thrown) {
-            this.argumentTypes = argumentTypes;
-            this.resultType = resultType;
-            this.thrown = thrown;
-        }
-        @Override
-        public int getTag() {
-            return TYPEFUNCTION;
-        }
-        @Override
-        public void accept(Visitor v) {
-            v.visitFunctionType(this);
-        }
-        @Override
-        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
-            return v.visitFunctionType(this, d);
-        }
-        public java.util.List<? extends Tree> getArgumentTypes() {
-            return argumentTypes;
-        }
-        public Tree getResultType() {
-            return resultType;
-        }
-        public java.util.List<? extends ExpressionTree> getThrownTypes() {
-            return thrown;
-        }
-        public Kind getKind() {
-            return Kind.FUNCTION_TYPE;
-        }
-    }
-
     /**
      * A formal class parameter.
      * @param name name
@@ -2400,7 +2354,6 @@
         public void visitTypeArray(JCArrayTypeTree that)     { visitTree(that); }
         public void visitTypeApply(JCTypeApply that)         { visitTree(that); }
         public void visitTypeDisjunction(JCTypeDisjunction that)   { visitTree(that); }
-        public void visitFunctionType(JCFunctionType that)   { visitTree(that); }
         public void visitTypeParameter(JCTypeParameter that) { visitTree(that); }
         public void visitWildcard(JCWildcard that)           { visitTree(that); }
         public void visitTypeBoundKind(TypeBoundKind that)   { visitTree(that); }
--- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Fri May 20 17:19:01 2011 +0100
@@ -1239,22 +1239,6 @@
         }
     }
 
-    public void visitFunctionType(JCFunctionType tree) {
-        try {
-            print("#");
-            print("(");
-            printExprs(tree.argumentTypes);
-            print(")");
-            if (tree.thrown.nonEmpty()) {
-                print("(");
-                printExprs(tree.thrown);
-                print(")");
-            }
-        } catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
     public void visitTypeParameter(JCTypeParameter tree) {
         try {
             print(tree.name);
--- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Fri May 20 17:19:01 2011 +0100
@@ -357,14 +357,6 @@
         return M.at(t.pos).TypeDisjunction(components);
     }
 
-    public JCTree visitFunctionType(FunctionTypeTree node, P p) {
-        JCFunctionType t = (JCFunctionType) node;
-        List<JCExpression> argtypes = copy(t.argumentTypes, p);
-        JCExpression restype = copy(t.resultType, p);
-        List<JCExpression> thrown = copy(t.thrown, p);
-        return M.at(t.pos).FunctionType(argtypes, restype, thrown);
-    }
-
     public JCTree visitArrayType(ArrayTypeTree node, P p) {
         JCArrayTypeTree t = (JCArrayTypeTree) node;
         JCExpression elemtype = copy(t.elemtype, p);
--- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Fri May 20 17:19:01 2011 +0100
@@ -455,12 +455,6 @@
         return tree;
     }
 
-    public JCFunctionType FunctionType(List<JCExpression> argtypes, JCExpression restype, List<JCExpression> thrown) {
-        JCFunctionType tree = new JCFunctionType(argtypes, restype, thrown);
-        tree.pos = pos;
-        return tree;
-    }
-
     public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
         return TypeParameter(0, name, bounds);
     }
--- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Fri May 20 17:19:01 2011 +0100
@@ -276,12 +276,6 @@
         scan(tree.elemtype);
     }
 
-    public void visitFunctionType(JCFunctionType tree) {
-        scan(tree.argumentTypes);
-        scan(tree.resultType);
-        scan(tree.thrown);
-    }
-
     public void visitTypeApply(JCTypeApply tree) {
         scan(tree.clazz);
         scan(tree.arguments);
--- a/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Fri May 20 17:19:01 2011 +0100
@@ -379,13 +379,6 @@
         result = tree;
     }
 
-    public void visitFunctionType(JCFunctionType tree) {
-        tree.argumentTypes = translate(tree.argumentTypes);
-        tree.resultType = translate(tree.resultType);
-        tree.thrown = translate(tree.thrown);
-        result = tree;
-    }
-
     public void visitTypeParameter(JCTypeParameter tree) {
         tree.bounds = translate(tree.bounds);
         result = tree;
--- a/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Thu May 05 15:47:56 2011 -0700
+++ b/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Fri May 20 17:19:01 2011 +0100
@@ -347,23 +347,21 @@
             return s;
         }
 
+        @SuppressWarnings("fallthrough")
         @Override
         public String visitForAll(ForAll t, Locale locale) {
-            if (types.isFunctionType(t)) {
-                return t.qtype.containsAny(t.tvars) ?
-                    localize(locale, "compiler.misc.type.lambda") :
-                    visit(t.qtype, locale);
+            switch (t.getPolyTag()) {
+                case POLY_LAMBDA:
+                case POLY_REFERENCE:
+                    String key = t.getPolyTag() == POLY_LAMBDA ?
+                        "compiler.misc.type.lambda" :
+                        "compiler.misc.type.mref";
+                    return t.qtype.tag == NONE ?
+                        localize(locale, key) :
+                        visit(t.qtype, locale);
+                default:
+                    return super.visitForAll(t, locale);
             }
-            else {
-                return super.visitForAll(t, locale);
-            }
-        }
-
-        @Override
-        public String visitFunctionType(FunctionType t, Locale locale) {
-            return (t.getReturnType().isErroneous()) ?
-                localize(locale, "compiler.misc.type.lambda") :
-                super.visitFunctionType(t, locale);
         }
 
         @Override
@@ -415,10 +413,7 @@
 
         @Override
         public String visitTypeVar(TypeVar t, Locale locale) {
-            if ((t.tsym.flags() & LAMBDA) != 0) {
-                return "?";
-            }
-            else if (unique(t) ||
+            if (unique(t) ||
                     !getConfiguration().isEnabled(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES)) {
                 return t.toString();
             }
@@ -456,7 +451,7 @@
                     ? ownerName
                     : s.name.toString();
                 if (s.type != null) {
-                    if (s.type.tag == FORALL) {
+                    if (s.type.isParameterized()) {
                         ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
                     }
                     ms += "(" + printMethodArgs(
@@ -489,28 +484,20 @@
         }
 
         @Override
-        public Void visitForAll(ForAll t, Void ignored) {            
-            visit(t.tvars);
+        public Void visitForAll(ForAll t, Void ignored) {
             visit(t.qtype);
             return null;
         }
 
         @Override
         public Void visitMethodType(MethodType t, Void ignored) {
+            visit(t.typeargs);
             visit(t.argtypes);
             visit(t.restype);
             return null;
         }
 
         @Override
-        public Void visitFunctionType(FunctionType t, Void ignored) {
-            visit(t.argtypes);
-            visit(t.restype);
-            visit(t.thrown);
-            return null;
-        }
-
-        @Override
         public Void visitDisjunctiveType(DisjunctiveType t, Void ignored) {
             if (indexOf(t, WhereClauseKind.DISJUNCTIVE) == -1) {
                 String subkey = t.alternatives.isEmpty() ?
@@ -581,8 +568,7 @@
 
         @Override
         public Void visitTypeVar(TypeVar t, Void ignored) {
-            if ((t.tsym.flags() & LAMBDA) == 0 &&
-                    indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
+            if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
                 //access the bound type and skip error types
                 Type bound = t.bound;
                 while ((bound instanceof ErrorType))
--- a/test/tools/javac/Diagnostics/6862608/T6862608a.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/Diagnostics/6862608/T6862608a.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-T6862608a.java:19:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator<T>, java.util.Comparator<java.lang.String>)), <T>java.util.Comparator<T>, java.util.Comparator<java.lang.String>
+T6862608a.java:19:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator<T>, java.util.Comparator<java.lang.String>)), java.util.Comparator<T>, java.util.Comparator<java.lang.String>
 - compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, java.lang.Object, kindname.method, <T>compound(java.lang.Iterable<? extends java.util.Comparator<? super T>>))}
 1 error
--- a/test/tools/javac/diags/examples.not-yet.txt	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/diags/examples.not-yet.txt	Fri May 20 17:19:01 2011 +0100
@@ -40,6 +40,7 @@
 compiler.err.type.var.more.than.once                    # UNUSED
 compiler.err.type.var.more.than.once.in.result          # UNUSED
 compiler.err.undetermined.type
+compiler.err.undetermined.type.1
 compiler.err.unexpected.type
 compiler.err.unknown.enum.constant                      # in bad class file
 compiler.err.unsupported.cross.fp.lit                   # Scanner: host system dependent
@@ -73,6 +74,7 @@
 compiler.misc.kindname.type.variable.bound
 compiler.misc.kindname.value
 compiler.misc.no.unique.minimal.instance.exists
+compiler.misc.no.unique.maximal.instance.exists
 compiler.misc.resume.abort                              # prompt for a response
 compiler.misc.source.unavailable                        # DiagnosticSource
 compiler.misc.token.bad-symbol
@@ -113,18 +115,15 @@
 compiler.warn.unchecked.cast.to.type                    # DEAD, replaced by compiler.misc.unchecked.cast.to.type
 compiler.warn.unexpected.archive.file                   # Paths: zip file with unknown extn
 compiler.err.bad.defender.method.body                                            #LAMBDA
+compiler.err.bad.lambda.token                                                    #LAMBDA
 compiler.err.break.inside.lambda                                                 #LAMBDA
-compiler.err.cant.apply.lambda                                                   #LAMBDA
 compiler.err.cant.ref.non.effectively.final.var                                  #LAMBDA
 compiler.err.cant.ret.void.expr                                                  #LAMBDA
 compiler.err.cont.inside.lambda                                                  #LAMBDA
 compiler.err.defender.methods.not.supported.in.source                            #LAMBDA
 compiler.err.disjoint.type.not.allowed.here                                      #LAMBDA
-compiler.err.func.types.not.supported.in.source                                  #LAMBDA
-compiler.err.incompatibles.ret.types.in.lambda                                   #LAMBDA
 compiler.err.invalid.target.type.for.lambda.conv                                 #LAMBDA
 compiler.err.invalid.target.type.for.lambda.conv.1                               #LAMBDA
-compiler.err.lambda.call.non.func.type                                           #LAMBDA
 compiler.err.lambda.not.supported.in.source                                      #LAMBDA
 compiler.err.method.references.not.supported.in.source                           #LAMBDA
 compiler.err.throw.typarams.not.supported.in.source                              #LAMBDA
@@ -135,13 +134,16 @@
 compiler.err.unexpected.lambda                                                   #LAMBDA
 compiler.err.unexpected.meth.reference                                           #LAMBDA
 compiler.misc.bad.defender.method                                                #LAMBDA
+compiler.misc.cyclic.lambda.inference                                            #LAMBDA
 compiler.misc.disjunctive.type                                                   #LAMBDA
 compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope              #LAMBDA
-compiler.misc.incompatible.target.in.lambda.conv                                 #LAMBDA
 compiler.misc.incompatible.targets.in.lambda.conv                                #LAMBDA
+compiler.misc.infer.varargs.argument.mismatch                                    #LAMBDA
+compiler.misc.infer.varargs.argument.mismatch.1                                  #LAMBDA
 compiler.misc.invalid.generic.target.for.lambda.conv                             #LAMBDA
 compiler.misc.lambda                                                             #LAMBDA
 compiler.misc.multiple.targets.for.lambda.conv                                   #LAMBDA
+compiler.misc.no.suitable.sam.inst                                               #LAMBDA
 compiler.misc.no.target.method.for.lambda.conv                                   #LAMBDA
 compiler.misc.target.for.lambda.conv.must.be.abstract                            #LAMBDA
 compiler.misc.target.for.lambda.conv.must.be.interface                           #LAMBDA
@@ -157,9 +159,10 @@
 compiler.misc.no.conforming.assignment.exists.1                                  #LAMBDA
 compiler.misc.varargs.argument.mismatch.1                                        #LAMBDA
 compiler.misc.type.lambda                                                        #LAMBDA
+compiler.misc.type.mref                                                          #LAMBDA
 compiler.misc.bad.enclosing.method                                               #LAMBDA
+compiler.misc.infer.incompatible.ret.types.in.lambda                             #LAMBDA
+compiler.misc.infer.incompatible.arg.types.in.lambda                             #LAMBDA
+compiler.misc.infer.incompatible.thrown.types.in.lambda                          #LAMBDA
 compiler.note.potential.lambda.found                                             #LAMBDA
-compiler.warn.cyclic.lambda.inference.throws                                     #LAMBDA
-compiler.warn.cyclic.lambda.inference.throws.1                                   #LAMBDA
-compiler.err.bad.lambda.token                                                    #LAMBDA
 compiler.warn.redundant.extension.keyword                                        #LAMBDA
--- a/test/tools/javac/diags/examples/UndeterminedType1.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.undetermined.type.1
-// key: compiler.misc.no.unique.maximal.instance.exists
-
-class UndeterminedType1<V> {
-    <T extends Integer & Runnable> UndeterminedType1<T> m() {
-        return null;
-    }
-
-
-    UndeterminedType1<? extends String> c2 = m();
-}
--- a/test/tools/javac/generics/inference/6315770/T6315770.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/generics/inference/6315770/T6315770.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-T6315770.java:16:42: compiler.err.undetermined.type.1: <T>T6315770<T>, (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
-T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, T6315770<T>, T6315770<? super java.lang.String>)), <T>T6315770<T>, T6315770<? super java.lang.String>
+T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.unique.maximal.instance.exists: T, java.lang.String,java.lang.Integer,java.lang.Runnable)), T6315770<T>, T6315770<? extends java.lang.String>
+T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, T6315770<T>, T6315770<? super java.lang.String>)), T6315770<T>, T6315770<? super java.lang.String>
 2 errors
--- a/test/tools/javac/generics/inference/6638712/T6638712a.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/generics/inference/6638712/T6638712a.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-T6638712a.java:16:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator<T>, java.util.Comparator<java.lang.String>)), <T>java.util.Comparator<T>, java.util.Comparator<java.lang.String>
+T6638712a.java:16:41: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, java.util.Comparator<T>, java.util.Comparator<java.lang.String>)), java.util.Comparator<T>, java.util.Comparator<java.lang.String>
 1 error
--- a/test/tools/javac/generics/inference/6638712/T6638712b.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/generics/inference/6638712/T6638712b.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: T, T, java.lang.String)), <T>T, java.lang.String
+T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: I,T, T, java.lang.String)), T, java.lang.String
 1 error
--- a/test/tools/javac/generics/inference/6638712/T6638712e.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/generics/inference/6638712/T6638712e.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: X, T6638712e.Foo<X,java.lang.String>, T6638712e.Foo<java.lang.Object,java.lang.String>)), <X>T6638712e.Foo<X,java.lang.String>, T6638712e.Foo<java.lang.Object,java.lang.String>
+T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: X, T6638712e.Foo<X,java.lang.String>, T6638712e.Foo<java.lang.Object,java.lang.String>)), T6638712e.Foo<X,java.lang.String>, T6638712e.Foo<java.lang.Object,java.lang.String>
 1 error
--- a/test/tools/javac/lambda/BadConv01.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @ignore
- * @summary check that target of SAM conversion can't be a generic method
- * @author  Alex Buckley
- * @compile/fail/ref=BadConv01.out -XDallowFunctionTypes -XDrawDiagnostics BadConv01.java
- */
-
-class BadConv01<T> {
-    #int(T) p = #(T x) { 10 };
-    interface Bar { <X> int m(X x); }
-
-    Bar b = p; // Illegal. Bar has an infinite number of members called m.
-}
--- a/test/tools/javac/lambda/BadConv02.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @ignore
- * @summary check that target of SAM conversion can't be an abstract class with non-default constructor
- * @author  Alex Buckley
- * @compile/fail/ref=BadConv02.out -XDallowFunctionTypes -XDrawDiagnostics BadConv02.java
- */
-
-class BadConv02 {
-
-    static abstract class Foo {
-        Foo(int x) {}
-        int m() { return 0; }
-    }
-
-    static class FooImpl extends Foo {
-        FooImpl(int x) { super(x); }
-        int m() { return 1; }
-    }
-
-    #int() x = #{ 42 };
-    Foo f_1 = new FooImpl();  // Illegal, of course.
-    Foo f_2 = x;  // x has no argument for Foo's constructor, so must be illegal like the FooImpl() line.
-}
--- a/test/tools/javac/lambda/BadConv03.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/BadConv03.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-BadConv03.java:40:11: compiler.err.invalid.target.type.for.lambda.conv.1: BadConv03.B, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, BadConv03.B)
+BadConv03.java:40:11: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, BadConv03.B)), compiler.misc.type.lambda, BadConv03.B
 1 error
--- a/test/tools/javac/lambda/BadLambdaPos.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/BadLambdaPos.out	Fri May 20 17:19:01 2011 +0100
@@ -1,11 +1,9 @@
 BadLambdaPos.java:39:14: compiler.err.unexpected.lambda
 BadLambdaPos.java:39:30: compiler.err.unexpected.lambda
-BadLambdaPos.java:39:28: compiler.err.operator.cant.be.applied.1: +, #void(int), #void(int)
 BadLambdaPos.java:40:14: compiler.err.unexpected.lambda
 BadLambdaPos.java:44:18: compiler.err.unexpected.lambda
 BadLambdaPos.java:44:34: compiler.err.unexpected.lambda
-BadLambdaPos.java:44:32: compiler.err.operator.cant.be.applied.1: +, #void(int), #void(int)
 BadLambdaPos.java:45:21: compiler.err.unexpected.lambda
-BadLambdaPos.java:49:22: compiler.err.invalid.target.type.for.lambda.conv.1: java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)
-BadLambdaPos.java:50:28: compiler.err.invalid.target.type.for.lambda.conv.1: java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)
-10 errors
+BadLambdaPos.java:49:22: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), compiler.misc.type.lambda, java.lang.Object
+BadLambdaPos.java:50:28: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), compiler.misc.type.lambda, java.lang.Object
+8 errors
--- a/test/tools/javac/lambda/BadReturn.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/BadReturn.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-BadReturn.java:42:42: compiler.err.prob.found.req: (compiler.misc.incompatible.types), void, java.lang.Comparable<?>
-BadReturn.java:47:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), void, java.lang.Comparable<?>
+BadReturn.java:42:42: compiler.err.cant.ret.void.expr
+BadReturn.java:47:45: compiler.err.cant.ret.void.expr
 2 errors
--- a/test/tools/javac/lambda/BadTargetType.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/BadTargetType.out	Fri May 20 17:19:01 2011 +0100
@@ -1,5 +1,5 @@
-BadTargetType.java:37:24: compiler.err.invalid.target.type.for.lambda.conv.1: java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)
-BadTargetType.java:38:17: compiler.err.invalid.target.type.for.lambda.conv.1: java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)
-BadTargetType.java:41:9: compiler.err.cant.apply.symbol.1: kindname.method, m1, java.lang.Object, #void(int), kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists.1: #void(int), java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object))
-BadTargetType.java:42:9: compiler.err.cant.apply.symbol.1: kindname.method, m2, java.lang.Object, #void(int), kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists.1: #void(int), java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object))
+BadTargetType.java:37:24: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), compiler.misc.type.lambda, java.lang.Object
+BadTargetType.java:38:17: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), compiler.misc.type.lambda, java.lang.Object
+BadTargetType.java:41:9: compiler.err.cant.apply.symbol.1: kindname.method, m1, java.lang.Object, compiler.misc.type.lambda, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists.1: compiler.misc.type.lambda, java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object))
+BadTargetType.java:42:9: compiler.err.cant.apply.symbol.1: kindname.method, m2, java.lang.Object, compiler.misc.type.lambda, kindname.class, BadTargetType, (compiler.misc.no.conforming.assignment.exists.1: compiler.misc.type.lambda, java.lang.Object, (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object))
 4 errors
--- a/test/tools/javac/lambda/FuncType01.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @ignore
- * @summary test function type with no arguments
- * @author  Maurizio Cimadamore
- * @compile -XDallowFunctionTypes FuncType01.java
- * @run main FuncType01
- */
-
-public class FuncType01 {
-
-    static void assertTrue(boolean cond) {
-        if (!cond)
-            throw new AssertionError();
-    }
-
-    public static void main(String[] args) {
-        #boolean() cond = #{ true };
-        assertTrue(cond.());
-    }
-}
--- a/test/tools/javac/lambda/LambdaCapture04.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaCapture04.java	Fri May 20 17:19:01 2011 +0100
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @ignore
  * @summary test for capture of non-mutable locals/outer fields in multiple scopes
  * @author  Maurizio Cimadamore
  * @run main LambdaCapture04
--- a/test/tools/javac/lambda/LambdaCapture05.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaCapture05.java	Fri May 20 17:19:01 2011 +0100
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @ignore
  * @summary test for capture in nested lambda expressions
  * @author  Maurizio Cimadamore
  * @run main LambdaCapture05
--- a/test/tools/javac/lambda/LambdaConv02.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaConv02.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-LambdaConv02.java:42:18: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv02.SAM, (compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope: null, kindname.class, LambdaConv02.SAM, LambdaConv02)
-LambdaConv02.java:43:9: compiler.err.cant.apply.symbol.1: kindname.method, test1, LambdaConv02.SAM, #void(), kindname.class, LambdaConv02, (compiler.misc.no.conforming.assignment.exists.1: #void(), LambdaConv02.SAM, (compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope: null, kindname.class, LambdaConv02.SAM, LambdaConv02))
+LambdaConv02.java:42:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope: null, kindname.class, LambdaConv02.SAM, LambdaConv02)), compiler.misc.type.lambda, LambdaConv02.SAM
+LambdaConv02.java:43:9: compiler.err.cant.apply.symbol.1: kindname.method, test1, LambdaConv02.SAM, compiler.misc.type.lambda, kindname.class, LambdaConv02, (compiler.misc.no.conforming.assignment.exists.1: compiler.misc.type.lambda, LambdaConv02.SAM, (compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope: null, kindname.class, LambdaConv02.SAM, LambdaConv02))
 2 errors
--- a/test/tools/javac/lambda/LambdaConv03.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaConv03.java	Fri May 20 17:19:01 2011 +0100
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @ignore
  * @summary SAM types and method type inference
  * @author  Brian Goetz
  * @author  Maurizio Cimadamore
--- a/test/tools/javac/lambda/LambdaConv04.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @ignore
- * @summary function type and method type inference
- * @author  Brian Goetz
- * @author  Maurizio Cimadamore
- * @compile -XDallowFunctionTypes LambdaConv04.java
- * @run main LambdaConv04
- */
-
-public class LambdaConv04 {
-
-    static int assertionCount = 0;
-
-    static void assertTrue(boolean cond) {
-        assertionCount++;
-        if (!cond)
-            throw new AssertionError();
-    }
-
-    public static <T, U> T exec(#T(U) lambda, U x) {
-        return lambda.(x);
-    }
-
-    static {
-        //void
-        exec(#(Integer x){ assertTrue(x == 3); }, 3);
-        //Covariant returns:
-        int i = exec(#(Integer x){ x }, 3);
-        assertTrue(3 == i);
-        //Method resolution with boxing:
-        int x = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == x);
-        //Runtime exception transparency:
-        try {
-            exec(#(Object x) { x.hashCode() }, null);
-        }
-        catch (RuntimeException e) {
-            assertTrue(true);
-        }
-    }
-
-    {
-        //void
-        exec(#(Integer x){ assertTrue(x == 3); }, 3);
-        //Covariant returns:
-        int i = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == i);
-        //Method resolution with boxing:
-        int x = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == x);
-        //Runtime exception transparency:
-        try {
-            exec(#(Object x) { x.hashCode() }, null);
-        }
-        catch (RuntimeException e) {
-            assertTrue(true);
-        }
-    }
-
-    public static void test1() {
-        //void
-        exec(#(Integer x){ assertTrue(x == 3); }, 3);
-        //Covariant returns:
-        int i = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == i);
-        //Method resolution with boxing:
-        int x = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == x);
-        //Runtime exception transparency:
-        try {
-            exec(#(Object x) { x.hashCode() }, null);
-        }
-        catch (RuntimeException e) {
-            assertTrue(true);
-        }
-    }
-
-    public void test2() {
-        //void
-        exec(#(Integer x){ assertTrue(x == 3); }, 3);
-        //Covariant returns:
-        int i = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == i);
-        //Method resolution with boxing:
-        int x = exec(#(Integer x) { x }, 3);
-        assertTrue(3 == x);
-        //Runtime exception transparency:
-        try {
-            exec(#(Object x) { x.hashCode() }, null);
-        }
-        catch (RuntimeException e) {
-            assertTrue(true);
-        }
-    }
-
-    public static void main(String[] args) {
-        test1();
-        new LambdaConv04().test2();
-        assertTrue(assertionCount == 16);
-    }
-}
--- a/test/tools/javac/lambda/LambdaConv09.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaConv09.out	Fri May 20 17:19:01 2011 +0100
@@ -1,6 +1,6 @@
-LambdaConv09.java:67:19: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv09.Foo1, (compiler.misc.no.target.method.for.lambda.conv: null, kindname.class, LambdaConv09.Foo1)
-LambdaConv09.java:68:19: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv09.Foo2, (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, LambdaConv09.Foo2)
-LambdaConv09.java:70:19: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv09.Bar3, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.class, LambdaConv09.Bar3)
-LambdaConv09.java:71:18: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv09.Quux, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.class, LambdaConv09.Quux)
-LambdaConv09.java:72:19: compiler.err.invalid.target.type.for.lambda.conv.1: LambdaConv09.Foo4, (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, LambdaConv09.Foo4)
+LambdaConv09.java:67:19: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.target.method.for.lambda.conv: null, kindname.class, LambdaConv09.Foo1)), compiler.misc.type.lambda, LambdaConv09.Foo1
+LambdaConv09.java:68:19: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, LambdaConv09.Foo2)), compiler.misc.type.lambda, LambdaConv09.Foo2
+LambdaConv09.java:70:19: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.class, LambdaConv09.Bar3)), compiler.misc.type.lambda, LambdaConv09.Bar3
+LambdaConv09.java:71:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.class, LambdaConv09.Quux)), compiler.misc.type.lambda, LambdaConv09.Quux
+LambdaConv09.java:72:19: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, LambdaConv09.Foo4)), compiler.misc.type.lambda, LambdaConv09.Foo4
 5 errors
--- a/test/tools/javac/lambda/LambdaConv10.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaConv10.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-LambdaConv10.java:36:44: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.incompatible.target.in.lambda.conv: call, kindname.interface, LambdaConv10.Method1)), #java.lang.Integer(int)(), LambdaConv10.Method1<java.lang.Integer,java.lang.Integer,>
+LambdaConv10.java:36:44: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.arg.types.in.lambda)), compiler.misc.type.lambda, LambdaConv10.Method1<java.lang.Integer,java.lang.Integer,>
 1 error
--- a/test/tools/javac/lambda/LambdaExprNotVoid.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/LambdaExprNotVoid.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-LambdaExprNotVoid.java:35:24: compiler.err.prob.found.req: (compiler.misc.incompatible.types), int, void
-LambdaExprNotVoid.java:36:24: compiler.err.prob.found.req: (compiler.misc.incompatible.types), int, void
+LambdaExprNotVoid.java:35:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.ret.types.in.lambda: int)), compiler.misc.type.lambda, LambdaExpr05.SAM
+LambdaExprNotVoid.java:36:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.ret.types.in.lambda: int)), compiler.misc.type.lambda, LambdaExpr05.SAM
 2 errors
--- a/test/tools/javac/lambda/MethodReference04.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/MethodReference04.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-MethodReference04.java:34:16: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), #void(java.lang.Integer), java.lang.Object
+MethodReference04.java:34:16: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.target.for.lambda.conv.must.be.abstract: null, kindname.class, java.lang.Object)), compiler.misc.type.mref, java.lang.Object
 1 error
--- a/test/tools/javac/lambda/MethodReference09.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/MethodReference09.out	Fri May 20 17:19:01 2011 +0100
@@ -1,4 +1,4 @@
 MethodReference09.java:42:23: compiler.err.non-static.cant.be.ref: kindname.method, getThis()
-MethodReference09.java:42:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference09.SAM)), #java.lang.String(), MethodReference09.SAM
+MethodReference09.java:42:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.arg.types.in.lambda)), compiler.misc.type.mref, MethodReference09.SAM
 MethodReference09.java:43:20: compiler.err.non-static.cant.be.ref: kindname.variable, this
 3 errors
--- a/test/tools/javac/lambda/MethodReference20.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/MethodReference20.out	Fri May 20 17:19:01 2011 +0100
@@ -1,5 +1,5 @@
-MethodReference20.java:42:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM)), #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer>
+MethodReference20.java:42:27: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.ret.types.in.lambda: MethodReference20<java.lang.String>)), compiler.misc.type.mref, MethodReference20.SAM<java.lang.Integer>
 MethodReference20.java:43:53: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null)
-MethodReference20.java:44:9: compiler.err.cant.apply.symbol.1: kindname.method, test, MethodReference20.SAM<java.lang.Integer>, #MethodReference20<java.lang.String>(java.lang.String), kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists.1: #MethodReference20<java.lang.String>(java.lang.String), MethodReference20.SAM<java.lang.Integer>, (compiler.misc.incompatible.target.in.lambda.conv: m, kindname.interface, MethodReference20.SAM))
+MethodReference20.java:44:9: compiler.err.cant.apply.symbol.1: kindname.method, test, MethodReference20.SAM<java.lang.Integer>, compiler.misc.type.mref, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists.1: compiler.misc.type.mref, MethodReference20.SAM<java.lang.Integer>, (compiler.misc.infer.incompatible.ret.types.in.lambda: MethodReference20<java.lang.String>))
 MethodReference20.java:45:40: compiler.err.cant.apply.symbol.1: kindname.constructor, MethodReference20, java.lang.String, java.lang.Integer, kindname.class, MethodReference20<X>, (compiler.misc.no.conforming.assignment.exists: java.lang.Integer, java.lang.String, null)
 4 errors
--- a/test/tools/javac/lambda/TargetType01.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType01.java	Fri May 20 17:19:01 2011 +0100
@@ -23,9 +23,9 @@
 
 /*
  * @test
- * @summary show that method resolution is not NP hard
+ * @summary check nested case of overload resolution and lambda parameter inference
  * @author  Maurizio Cimadamore
- * @compile/fail/ref=TargetType01.out -XDlambdaInferenceDiags=false -XDrawDiagnostics TargetType01.java
+ * @compile TargetType01.java
  */
 
 class TargetType01 {
--- a/test/tools/javac/lambda/TargetType01.out	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-TargetType01.java:45:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
-TargetType01.java:45:33: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01
-2 errors
--- a/test/tools/javac/lambda/TargetType04.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType04.out	Fri May 20 17:19:01 2011 +0100
@@ -1,3 +1,3 @@
-TargetType04.java:37:29: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: ?, #?(?), TargetType04.S<java.lang.Double,java.lang.Integer>)), compiler.misc.type.lambda, TargetType04.S<java.lang.Double,java.lang.Integer>
-TargetType04.java:38:29: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: ?, #?(?), TargetType04.S<java.lang.Integer,java.lang.Double>)), compiler.misc.type.lambda, TargetType04.S<java.lang.Integer,java.lang.Double>
+TargetType04.java:37:29: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.ret.types.in.lambda: java.lang.Double)), compiler.misc.type.lambda, TargetType04.S<java.lang.Double,java.lang.Integer>
+TargetType04.java:38:29: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.incompatible.ret.types.in.lambda: java.lang.Integer)), compiler.misc.type.lambda, TargetType04.S<java.lang.Integer,java.lang.Double>
 2 errors
--- a/test/tools/javac/lambda/TargetType06.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType06.java	Fri May 20 17:19:01 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @summary check complex case of target typing
  * @author  Maurizio Cimadamore
- * @compile TargetType06.java
+ * @compile/fail/ref=TargetType06.out -XDrawDiagnostics TargetType06.java
  */
 
 import java.util.List;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType06.out	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,2 @@
+TargetType06.java:46:23: compiler.err.cant.apply.symbol.1: kindname.method, map, TargetType06.Function<B,B>, compiler.misc.type.lambda, kindname.class, TargetType06, (compiler.misc.cyclic.lambda.inference)
+1 error
--- a/test/tools/javac/lambda/TargetType09.java	Thu May 05 15:47:56 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @ignore
- * @summary check that explicit non-generic target type parses w/o problems
- * @author  Peter Levart
- * @author  Maurizio Cimadamore
- * @compile -XDallowFunctionTypes TargetType09.java
- */
-
-class TargetType09 {
-    public static #int() twice(final int value) { return null; }
-    public static #int() twice(final #int() func) { return null; }
-
-    public static void main(String[] args) {
-        System.out.println(twice(#{22}).());
-    }
-}
--- a/test/tools/javac/lambda/TargetType10.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType10.java	Fri May 20 17:19:01 2011 +0100
@@ -25,7 +25,7 @@
  * @test
  * @summary check that wildcards in the target method of a lambda conversion is handled correctly
  * @author  Maurizio Cimadamore
- * @compile TargetType10.java
+ * @compile/fail/ref=TargetType10.out -XDrawDiagnostics TargetType10.java
  */
 
 class TargetType10 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType10.out	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,2 @@
+TargetType10.java:38:11: compiler.err.cant.apply.symbol.1: kindname.method, compose, TargetType10.Function<B,C>,TargetType10.Function<A,? extends B>, compiler.misc.type.lambda,compiler.misc.type.lambda, kindname.class, TargetType10.Test, (compiler.misc.cyclic.lambda.inference)
+1 error
--- a/test/tools/javac/lambda/TargetType11.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType11.java	Fri May 20 17:19:01 2011 +0100
@@ -25,7 +25,7 @@
  * @test
  * @summary check that wildcards in the target method of a lambda conversion is handled correctly
  * @author  Maurizio Cimadamore
- * @compile TargetType11.java
+ * @compile/fail/ref=TargetType11.out -Xlint:unchecked -XDrawDiagnostics TargetType11.java
  */
 
 class TargetType11 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType11.out	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,4 @@
+TargetType11.java:37:61: compiler.warn.unchecked.varargs.non.reifiable.type: TargetType11.Predicate<? super T>
+TargetType11.java:41:32: compiler.err.cant.apply.symbol.1: kindname.method, and, TargetType11.Predicate<? super T>[], compiler.misc.type.lambda,compiler.misc.type.lambda, kindname.class, TargetType11.Test, (compiler.misc.cyclic.lambda.inference)
+1 error
+1 warning
--- a/test/tools/javac/lambda/TargetType14.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/TargetType14.out	Fri May 20 17:19:01 2011 +0100
@@ -1,7 +1,2 @@
-TargetType14.java:38:27: compiler.warn.cyclic.lambda.inference.throws.1: i,j
-TargetType14.java:39:11: compiler.warn.cyclic.lambda.inference.throws.1: i,j
-TargetType14.java:40:30: compiler.warn.cyclic.lambda.inference.throws.1: i,j
-TargetType14.java:41:30: compiler.warn.cyclic.lambda.inference.throws.1: i,j
-TargetType14.java:41:48: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.String, java.lang.Integer
+TargetType14.java:41:29: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.infer.no.conforming.instance.exists: X, TargetType14.SAM<java.lang.String>, TargetType14.SAM<java.lang.Integer>)), TargetType14.SAM<java.lang.String>, TargetType14.SAM<java.lang.Integer>
 1 error
-4 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType19.java	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary complex case of generic method call with lambda argument where target
+ *          is a wildcard SAM
+ * @compile TargetType19.java
+ */
+import java.util.List;
+
+class TargetType19 {
+
+    interface SAM<X> {
+        void f(List<? extends X> i);
+    }
+
+    <Z> void call(SAM<? extends Z> s, Z z) {  }
+
+   { call(#{ List<? extends String> p -> }, 1); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType19.out	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,2 @@
+TargetType19.java:40:10: compiler.err.invalid.inferred.types: (compiler.misc.no.conforming.assignment.exists: TargetType19.SAM<java.lang.String>, TargetType19.SAM<? extends java.lang.Integer>)
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType20.java	Fri May 20 17:19:01 2011 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary complex case of lambda return type that depends on generic method
+ *          inference variable
+ * @compile TargetType20.java
+ */
+import java.util.*;
+
+class TargetType20 {
+
+    interface SAM2<X> {
+      List<X> f();
+    }
+
+    class Test {
+       <Z> void call(SAM2<Z> x, SAM2<Z> y) { }
+       { call(#{ -> Collections.emptyList() }, #{ -> new ArrayList<String>() }); }
+    }
+}
--- a/test/tools/javac/lambda/badMemberRefBytecode/Main.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/badMemberRefBytecode/Main.java	Fri May 20 17:19:01 2011 +0100
@@ -1,5 +1,4 @@
 import java.util.Collections;
-import java.util.Locale;
 
 public class Main {
 
--- a/test/tools/javac/lambda/sqe/SAM_types/NonSAM1.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/sqe/SAM_types/NonSAM1.out	Fri May 20 17:19:01 2011 +0100
@@ -1,2 +1,2 @@
-NonSAM1.java:9:20: compiler.err.invalid.target.type.for.lambda.conv.1: Planet, (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, Planet)
+NonSAM1.java:9:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.no.target.method.for.lambda.conv: null, kindname.interface, Planet)), compiler.misc.type.lambda, Planet
 1 error
--- a/test/tools/javac/lambda/sqe/SAM_types/NonSAM3.out	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/lambda/sqe/SAM_types/NonSAM3.out	Fri May 20 17:19:01 2011 +0100
@@ -1,9 +1,9 @@
-NonSAM3.java:13:21: compiler.err.invalid.target.type.for.lambda.conv.1: FooBar, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, FooBar)
-NonSAM3.java:14:22: compiler.err.invalid.target.type.for.lambda.conv.1: FooBar, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, FooBar)
-NonSAM3.java:15:17: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
-NonSAM3.java:16:18: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
-NonSAM3.java:17:18: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
-NonSAM3.java:18:18: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
-NonSAM3.java:19:18: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
-NonSAM3.java:20:18: compiler.err.invalid.target.type.for.lambda.conv.1: DE, (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)
+NonSAM3.java:13:21: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, FooBar)), compiler.misc.type.lambda, FooBar
+NonSAM3.java:14:22: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, FooBar)), compiler.misc.type.lambda, FooBar
+NonSAM3.java:15:17: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
+NonSAM3.java:16:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
+NonSAM3.java:17:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
+NonSAM3.java:18:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
+NonSAM3.java:19:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
+NonSAM3.java:20:18: compiler.err.prob.found.req: (compiler.misc.incompatible.types.1: (compiler.misc.multiple.targets.for.lambda.conv: null, kindname.interface, DE)), compiler.misc.type.lambda, DE
 8 errors
--- a/test/tools/javac/types/TypeHarness.java	Thu May 05 15:47:56 2011 -0700
+++ b/test/tools/javac/types/TypeHarness.java	Fri May 20 17:19:01 2011 +0100
@@ -123,7 +123,7 @@
 
     /** assert that 's' is/is not castable to 't' */
     public void assertCastable(Type s, Type t, boolean expected) {
-        if (types.isCastableNoCheck(s, t) != expected) {
+        if (types.isCastable(s, t) != expected) {
             String msg = expected ?
                 " is not castable to " :
                 " is castable to ";
@@ -138,7 +138,7 @@
 
     /** assert that 's' is/is not convertible (method invocation conversion) to 't' */
     public void assertConvertible(Type s, Type t, boolean expected) {
-        if (types.isConvertibleNoCheck(s, t) != expected) {
+        if (types.isConvertible(s, t) != expected) {
             String msg = expected ?
                 " is not convertible to " :
                 " is convertible to ";
@@ -153,7 +153,7 @@
 
     /** assert that 's' is/is not assignable to 't' */
     public void assertAssignable(Type s, Type t, boolean expected) {
-        if (types.isAssignableNoCheck(s, t) != expected) {
+        if (types.isAssignable(s, t) != expected) {
             String msg = expected ?
                 " is not assignable to " :
                 " is assignable to ";