changeset 14064:539f9d08a9e5

Merge
author lana
date Thu, 11 Oct 2012 17:00:54 -0700
parents 4982fb064a47 5464cc907228
children a5c547191d8b
files
diffstat 153 files changed, 6687 insertions(+), 1243 deletions(-) [+]
line wrap: on
line diff
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassUseWriter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -195,10 +195,7 @@
         ClassUseWriter clsgen;
         String path = DirectoryManager.getDirectoryPath(classdoc.
                                                             containingPackage());
-        if (path.length() > 0) {
-            path += File.separator;
-        }
-        path += "class-use";
+        path += "class-use" + DirectoryManager.URL_FILE_SEPARATOR;
         String filename = classdoc.name() + ".html";
         String pkgname = classdoc.containingPackage().name();
         pkgname += (pkgname.length() > 0)? ".class-use": "class-use";
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HelpWriter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -302,7 +302,9 @@
         Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
                 getResource("doclet.Constants_Summary"));
         Content liConst = HtmlTree.LI(HtmlStyle.blockList, constHead);
-        Content line29 = getResource("doclet.Help_line_29");
+        Content line29 = getResource("doclet.Help_line_29",
+                getHyperLinkString("constant-values.html",
+                configuration.getText("doclet.Constants_Summary")));
         Content constPara = HtmlTree.P(line29);
         liConst.addContent(constPara);
         ul.addContent(liConst);
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties	Thu Oct 11 17:00:54 2012 -0700
@@ -160,7 +160,7 @@
 doclet.Help_line_26=These links show and hide the HTML frames.  All pages are available with or without frames.
 doclet.Help_line_27=The {0} link shows all classes and interfaces except non-static nested types.
 doclet.Help_line_28=Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
-doclet.Help_line_29=The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.
+doclet.Help_line_29=The {0} page lists the static final fields and their values.
 doclet.Help_line_30=This help file applies to API documentation generated using the standard doclet.
 doclet.Help_enum_line_1=Each enum has its own separate page with the following sections:
 doclet.Help_enum_line_2=Enum declaration
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java	Thu Oct 11 17:00:54 2012 -0700
@@ -488,17 +488,18 @@
     }
 
     /**
-     * Add a traliling file separator, if not found or strip off extra trailing
-     * file separators if any.
+     * Add a trailing file separator, if not found. Remove superfluous
+     * file separators if any. Preserve the front double file separator for
+     * UNC paths.
      *
      * @param path Path under consideration.
      * @return String Properly constructed path string.
      */
-    String addTrailingFileSep(String path) {
+    public static String addTrailingFileSep(String path) {
         String fs = System.getProperty("file.separator");
         String dblfs = fs + fs;
         int indexDblfs;
-        while ((indexDblfs = path.indexOf(dblfs)) >= 0) {
+        while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
             path = path.substring(0, indexDblfs) +
                 path.substring(indexDblfs + fs.length());
         }
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Thu Oct 11 17:00:54 2012 -0700
@@ -262,11 +262,7 @@
                 urls[count++] = url;
             }
         }
-        if (urls.length != count) {
-            URL[] tmp = new URL[count];
-            System.arraycopy(urls, 0, tmp, 0, count);
-            urls = tmp;
-        }
+        urls = Arrays.copyOf(urls, count);
         return urls;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java	Thu Oct 11 17:00:54 2012 -0700
@@ -136,4 +136,11 @@
         throw new IllegalStateException();
     }
 
+    /**
+     * For internal use only.  This method will be
+     * removed without warning.
+     */
+    public void updateContext(Context newContext) {
+        context = newContext;
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/api/MultiTaskListener.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/MultiTaskListener.java	Thu Oct 11 17:00:54 2012 -0700
@@ -79,10 +79,8 @@
             if (ccw.unwrap(l) == listener)
                 throw new IllegalStateException();
         }
-        TaskListener[] newListeners = new TaskListener[listeners.length + 1];
-        System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
-        newListeners[newListeners.length - 1] = ccw.wrap(listener);
-        listeners = newListeners;
+        listeners = Arrays.copyOf(listeners, listeners.length + 1);
+        listeners[listeners.length - 1] = ccw.wrap(listener);
     }
 
     public void remove(TaskListener listener) {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Oct 11 17:00:54 2012 -0700
@@ -28,6 +28,7 @@
 import java.util.EnumSet;
 import java.util.Locale;
 
+import com.sun.source.tree.MemberReferenceTree;
 import com.sun.tools.javac.api.Formattable;
 import com.sun.tools.javac.api.Messages;
 
@@ -85,11 +86,12 @@
     public static final int AMBIGUOUS    = ERRONEOUS+1; // ambiguous reference
     public static final int HIDDEN       = ERRONEOUS+2; // hidden method or field
     public static final int STATICERR    = ERRONEOUS+3; // nonstatic member from static context
-    public static final int ABSENT_VAR   = ERRONEOUS+4; // missing variable
-    public static final int WRONG_MTHS   = ERRONEOUS+5; // methods with wrong arguments
-    public static final int WRONG_MTH    = ERRONEOUS+6; // one method with wrong arguments
-    public static final int ABSENT_MTH   = ERRONEOUS+7; // missing method
-    public static final int ABSENT_TYP   = ERRONEOUS+8; // missing type
+    public static final int MISSING_ENCL = ERRONEOUS+4; // missing enclosing class
+    public static final int ABSENT_VAR   = ERRONEOUS+5; // missing variable
+    public static final int WRONG_MTHS   = ERRONEOUS+6; // methods with wrong arguments
+    public static final int WRONG_MTH    = ERRONEOUS+7; // one method with wrong arguments
+    public static final int ABSENT_MTH   = ERRONEOUS+8; // missing method
+    public static final int ABSENT_TYP   = ERRONEOUS+9; // missing type
 
     public enum KindName implements Formattable {
         ANNOTATION("kindname.annotation"),
@@ -140,6 +142,14 @@
         }
     }
 
+    public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
+        switch (mode) {
+            case INVOKE: return KindName.METHOD;
+            case NEW: return KindName.CONSTRUCTOR;
+            default : throw new AssertionError("Unexpected mode: "+ mode);
+        }
+    }
+
     /** A KindName representing a given symbol
      */
     public static KindName kindName(Symbol sym) {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Thu Oct 11 17:00:54 2012 -0700
@@ -30,6 +30,10 @@
 import com.sun.tools.javac.api.Messages;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.Pretty;
+import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
 
@@ -51,6 +55,8 @@
     List<Type> seenCaptured = List.nil();
     static final int PRIME = 997;  // largest prime less than 1000
 
+    protected Printer() { }
+
     /**
      * This method should be overriden in order to provide proper i18n support.
      *
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java	Thu Oct 11 17:00:54 2012 -0700
@@ -194,6 +194,9 @@
     public boolean allowObjectToPrimitiveCast() {
         return compareTo(JDK1_7) >= 0;
     }
+    public boolean allowPoly() {
+        return compareTo(JDK1_8) >= 0;
+    }
     public boolean allowLambda() {
         return compareTo(JDK1_8) >= 0;
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Oct 11 17:00:54 2012 -0700
@@ -168,6 +168,10 @@
         return owner;
     }
 
+    public Symbol baseSymbol() {
+        return this;
+    }
+
     /** The symbol's erased type.
      */
     public Type erasure(Types types) {
@@ -918,7 +922,12 @@
         /** Clone this symbol with new owner.
          */
         public VarSymbol clone(Symbol newOwner) {
-            VarSymbol v = new VarSymbol(flags_field, name, type, newOwner);
+            VarSymbol v = new VarSymbol(flags_field, name, type, newOwner) {
+                @Override
+                public Symbol baseSymbol() {
+                    return VarSymbol.this;
+                }
+            };
             v.pos = pos;
             v.adr = adr;
             v.data = data;
@@ -1045,7 +1054,12 @@
         /** Clone this symbol with new owner.
          */
         public MethodSymbol clone(Symbol newOwner) {
-            MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner);
+            MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner) {
+                @Override
+                public Symbol baseSymbol() {
+                    return MethodSymbol.this;
+                }
+            };
             m.code = code;
             return m;
         }
@@ -1068,6 +1082,10 @@
             }
         }
 
+        public boolean isDynamic() {
+            return false;
+        }
+
         /** find a symbol that this (proxy method) symbol implements.
          *  @param    c       The class whose members are searched for
          *                    implementations
@@ -1356,6 +1374,27 @@
         }
     }
 
+    /** A class for invokedynamic method calls.
+     */
+    public static class DynamicMethodSymbol extends MethodSymbol {
+
+        public Object[] staticArgs;
+        public Symbol bsm;
+        public int bsmKind;
+
+        public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
+            super(0, name, type, owner);
+            this.bsm = bsm;
+            this.bsmKind = bsmKind;
+            this.staticArgs = staticArgs;
+        }
+
+        @Override
+        public boolean isDynamic() {
+            return true;
+        }
+    }
+
     /** A class for predefined operators.
      */
     public static class OperatorSymbol extends MethodSymbol {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Oct 11 17:00:54 2012 -0700
@@ -126,6 +126,7 @@
     public final Type cloneableType;
     public final Type serializableType;
     public final Type methodHandleType;
+    public final Type methodTypeType;
     public final Type nativeHeaderType;
     public final Type throwableType;
     public final Type errorType;
@@ -182,6 +183,10 @@
      */
     public final Name[] boxedName = new Name[TypeTags.TypeTagCount];
 
+    /** A set containing all operator names.
+     */
+    public final Set<Name> operatorNames = new HashSet<Name>();
+
     /** A hashtable containing the encountered top-level and member classes,
      *  indexed by flat names. The table does not contain local classes.
      *  It should be updated from the outside to reflect classes defined
@@ -243,7 +248,7 @@
                             int opcode) {
         predefClass.members().enter(
             new OperatorSymbol(
-                names.fromString(name),
+                makeOperatorName(name),
                 new MethodType(List.of(left, right), res,
                                List.<Type>nil(), methodClass),
                 opcode,
@@ -274,7 +279,7 @@
                                      Type res,
                                      int opcode) {
         OperatorSymbol sym =
-            new OperatorSymbol(names.fromString(name),
+            new OperatorSymbol(makeOperatorName(name),
                                new MethodType(List.of(arg),
                                               res,
                                               List.<Type>nil(),
@@ -285,6 +290,16 @@
         return sym;
     }
 
+    /**
+     * Create a new operator name from corresponding String representation
+     * and add the name to the set of known operator names.
+     */
+    private Name makeOperatorName(String name) {
+        Name opName = names.fromString(name);
+        operatorNames.add(opName);
+        return opName;
+    }
+
     /** Enter a class into symbol table.
      *  @param    The name of the class.
      */
@@ -440,6 +455,7 @@
         throwableType = enterClass("java.lang.Throwable");
         serializableType = enterClass("java.io.Serializable");
         methodHandleType = enterClass("java.lang.invoke.MethodHandle");
+        methodTypeType = enterClass("java.lang.invoke.MethodType");
         errorType = enterClass("java.lang.Error");
         illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
         interruptedExceptionType = enterClass("java.lang.InterruptedException");
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Thu Oct 11 17:00:54 2012 -0700
@@ -27,14 +27,19 @@
 
 import java.util.Collections;
 
+import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.code.Symbol.*;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
 
 import javax.lang.model.type.*;
 
+import static com.sun.tools.javac.code.BoundKind.*;
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.BoundKind.*;
 import static com.sun.tools.javac.code.TypeTags.*;
 
 /** This class represents Java types. The class itself defines the behavior of
@@ -70,6 +75,9 @@
     /** Constant type: no type at all. */
     public static final JCNoType noType = new JCNoType(NONE);
 
+    /** Constant type: special type to be used during recovery of deferred expressions. */
+    public static final JCNoType recoveryType = new JCNoType(NONE);
+
     /** If this switch is turned on, the names of type variables
      *  and anonymous classes are printed with hashcodes appended.
      */
@@ -1168,22 +1176,59 @@
         }
     }
 
-    /** A class for instantiatable variables, for use during type
-     *  inference.
+    /** A class for inference variables, for use during method/diamond type
+     *  inference. An inference variable has upper/lower bounds and a set
+     *  of equality constraints. Such bounds are set during subtyping, type-containment,
+     *  type-equality checks, when the types being tested contain inference variables.
+     *  A change listener can be attached to an inference variable, to receive notifications
+     *  whenever the bounds of an inference variable change.
      */
     public static class UndetVar extends DelegatedType {
-        public List<Type> lobounds = List.nil();
-        public List<Type> hibounds = List.nil();
-        public List<Type> eq = List.nil();
+
+        /** Inference variable change listener. The listener method is called
+         *  whenever a change to the inference variable's bounds occurs
+         */
+        public interface UndetVarListener {
+            /** called when some inference variable bounds (of given kinds ibs) change */
+            void varChanged(UndetVar uv, Set<InferenceBound> ibs);
+        }
+
+        /**
+         * Inference variable bound kinds
+         */
+        public enum InferenceBound {
+            /** upper bounds */
+            UPPER,
+            /** lower bounds */
+            LOWER,
+            /** equality constraints */
+            EQ;
+        }
+
+        /** inference variable bounds */
+        private Map<InferenceBound, List<Type>> bounds;
+
+        /** inference variable's inferred type (set from Infer.java) */
         public Type inst = null;
 
+        /** inference variable's change listener */
+        public UndetVarListener listener = null;
+
         @Override
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitUndetVar(this, s);
         }
 
-        public UndetVar(Type origin) {
+        public UndetVar(TypeVar origin, Types types) {
+            this(origin, types, true);
+        }
+
+        public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
             super(UNDETVAR, origin);
+            bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
+            bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil());
+            bounds.put(InferenceBound.LOWER, List.<Type>nil());
+            bounds.put(InferenceBound.EQ, List.<Type>nil());
         }
 
         public String toString() {
@@ -1195,6 +1240,48 @@
             if (inst != null) return inst.baseType();
             else return this;
         }
+
+        /** get all bounds of a given kind */
+        public List<Type> getBounds(InferenceBound ib) {
+            return bounds.get(ib);
+        }
+
+        /** add a bound of a given kind - this might trigger listener notification */
+        public void addBound(InferenceBound ib, Type bound, Types types) {
+            List<Type> prevBounds = bounds.get(ib);
+            for (Type b : prevBounds) {
+                if (types.isSameType(b, bound)) {
+                    return;
+                }
+            }
+            bounds.put(ib, prevBounds.prepend(bound));
+            notifyChange(EnumSet.of(ib));
+        }
+
+        /** replace types in all bounds - this might trigger listener notification */
+        public void substBounds(List<Type> from, List<Type> to, Types types) {
+            EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
+            Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
+            for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
+                InferenceBound ib = _entry.getKey();
+                List<Type> prevBounds = _entry.getValue();
+                List<Type> newBounds = types.subst(prevBounds, from, to);
+                bounds2.put(ib, newBounds);
+                if (prevBounds != newBounds) {
+                    changed.add(ib);
+                }
+            }
+            if (!changed.isEmpty()) {
+                bounds = bounds2;
+                notifyChange(changed);
+            }
+        }
+
+        private void notifyChange(EnumSet<InferenceBound> ibs) {
+            if (listener != null) {
+                listener.varChanged(this, ibs);
+            }
+        }
     }
 
     /** Represents VOID or NONE.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeTags.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeTags.java	Thu Oct 11 17:00:54 2012 -0700
@@ -102,9 +102,13 @@
      */
     public static final int FORALL = WILDCARD+1;
 
+    /** The tag of deferred expression types in method context
+     */
+    public static final int DEFERRED = FORALL+1;
+
     /** The tag of the bottom type <null>.
      */
-    public static final int BOT = FORALL+1;
+    public static final int BOT = DEFERRED+1;
 
     /** The tag of a missing type.
      */
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Oct 11 17:00:54 2012 -0700
@@ -34,6 +34,7 @@
 import com.sun.tools.javac.jvm.ClassReader;
 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
 import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
 import com.sun.tools.javac.comp.Check;
 
 import static com.sun.tools.javac.code.Scope.*;
@@ -78,8 +79,10 @@
     final boolean allowObjectToPrimitiveCast;
     final ClassReader reader;
     final Check chk;
+    JCDiagnostic.Factory diags;
     List<Warner> warnStack = List.nil();
     final Name capturedName;
+    private final FunctionDescriptorLookupError functionDescriptorLookupError;
 
     // <editor-fold defaultstate="collapsed" desc="Instantiating">
     public static Types instance(Context context) {
@@ -101,6 +104,8 @@
         chk = Check.instance(context);
         capturedName = names.fromString("<captured wildcard>");
         messages = JavacMessages.instance(context);
+        diags = JCDiagnostic.Factory.instance(context);
+        functionDescriptorLookupError = new FunctionDescriptorLookupError();
     }
     // </editor-fold>
 
@@ -295,6 +300,294 @@
     }
     // </editor-fold>
 
+    // <editor-fold defaultstate="collapsed" desc="findSam">
+
+    /**
+     * Exception used to report a function descriptor lookup failure. The exception
+     * wraps a diagnostic that can be used to generate more details error
+     * messages.
+     */
+    public static class FunctionDescriptorLookupError extends RuntimeException {
+        private static final long serialVersionUID = 0;
+
+        JCDiagnostic diagnostic;
+
+        FunctionDescriptorLookupError() {
+            this.diagnostic = null;
+        }
+
+        FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
+            this.diagnostic = diag;
+            return this;
+        }
+
+        public JCDiagnostic getDiagnostic() {
+            return diagnostic;
+        }
+    }
+
+    /**
+     * A cache that keeps track of function descriptors associated with given
+     * functional interfaces.
+     */
+    class DescriptorCache {
+
+        private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>();
+
+        class FunctionDescriptor {
+            Symbol descSym;
+
+            FunctionDescriptor(Symbol descSym) {
+                this.descSym = descSym;
+            }
+
+            public Symbol getSymbol() {
+                return descSym;
+            }
+
+            public Type getType(Type origin) {
+                return memberType(origin, descSym);
+            }
+        }
+
+        class Entry {
+            final FunctionDescriptor cachedDescRes;
+            final int prevMark;
+
+            public Entry(FunctionDescriptor cachedDescRes,
+                    int prevMark) {
+                this.cachedDescRes = cachedDescRes;
+                this.prevMark = prevMark;
+            }
+
+            boolean matches(int mark) {
+                return  this.prevMark == mark;
+            }
+        }
+
+        FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
+            Entry e = _map.get(origin);
+            CompoundScope members = membersClosure(origin.type, false);
+            if (e == null ||
+                    !e.matches(members.getMark())) {
+                FunctionDescriptor descRes = findDescriptorInternal(origin, members);
+                _map.put(origin, new Entry(descRes, members.getMark()));
+                return descRes;
+            }
+            else {
+                return e.cachedDescRes;
+            }
+        }
+
+        /**
+         * Scope filter used to skip methods that should be ignored during
+         * function interface conversion (such as methods overridden by
+         * j.l.Object)
+         */
+        class DescriptorFilter implements Filter<Symbol> {
+
+            TypeSymbol origin;
+
+            DescriptorFilter(TypeSymbol origin) {
+                this.origin = origin;
+            }
+
+            @Override
+            public boolean accepts(Symbol sym) {
+                    return sym.kind == Kinds.MTH &&
+                            (sym.flags() & ABSTRACT) != 0 &&
+                            !overridesObjectMethod(origin, sym) &&
+                            notOverridden(sym);
+            }
+
+            private boolean notOverridden(Symbol msym) {
+                Symbol impl = ((MethodSymbol)msym).implementation(origin, Types.this, false);
+                return impl == null || (impl.flags() & ABSTRACT) != 0;
+            }
+        };
+
+        /**
+         * Compute the function descriptor associated with a given functional interface
+         */
+        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
+            if (!origin.isInterface()) {
+                //t must be an interface
+                throw failure("not.a.functional.intf");
+            }
+
+            final ListBuffer<Symbol> abstracts = ListBuffer.lb();
+            for (Symbol sym : membersCache.getElements(new DescriptorFilter(origin))) {
+                Type mtype = memberType(origin.type, sym);
+                if (abstracts.isEmpty() ||
+                        (sym.name == abstracts.first().name &&
+                        overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
+                    abstracts.append(sym);
+                } else {
+                    //the target method(s) should be the only abstract members of t
+                    throw failure("not.a.functional.intf.1",
+                            diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
+                }
+            }
+            if (abstracts.isEmpty()) {
+                //t must define a suitable non-generic method
+                throw failure("not.a.functional.intf.1",
+                            diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
+            } else if (abstracts.size() == 1) {
+                if (abstracts.first().type.tag == FORALL) {
+                    throw failure("invalid.generic.desc.in.functional.intf",
+                            abstracts.first(),
+                            Kinds.kindName(origin),
+                            origin);
+                } else {
+                    return new FunctionDescriptor(abstracts.first());
+                }
+            } else { // size > 1
+                for (Symbol msym : abstracts) {
+                    if (msym.type.tag == FORALL) {
+                        throw failure("invalid.generic.desc.in.functional.intf",
+                                abstracts.first(),
+                                Kinds.kindName(origin),
+                                origin);
+                    }
+                }
+                FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
+                if (descRes == null) {
+                    //we can get here if the functional interface is ill-formed
+                    ListBuffer<JCDiagnostic> descriptors = ListBuffer.lb();
+                    for (Symbol desc : abstracts) {
+                        String key = desc.type.getThrownTypes().nonEmpty() ?
+                                "descriptor.throws" : "descriptor";
+                        descriptors.append(diags.fragment(key, desc.name,
+                                desc.type.getParameterTypes(),
+                                desc.type.getReturnType(),
+                                desc.type.getThrownTypes()));
+                    }
+                    JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
+                            new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
+                            Kinds.kindName(origin), origin), descriptors.toList());
+                    throw failure(incompatibleDescriptors);
+                }
+                return descRes;
+            }
+        }
+
+        /**
+         * Compute a synthetic type for the target descriptor given a list
+         * of override-equivalent methods in the functional interface type.
+         * The resulting method type is a method type that is override-equivalent
+         * and return-type substitutable with each method in the original list.
+         */
+        private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
+            //pick argument types - simply take the signature that is a
+            //subsignature of all other signatures in the list (as per JLS 8.4.2)
+            List<Symbol> mostSpecific = List.nil();
+            outer: for (Symbol msym1 : methodSyms) {
+                Type mt1 = memberType(origin.type, msym1);
+                for (Symbol msym2 : methodSyms) {
+                    Type mt2 = memberType(origin.type, msym2);
+                    if (!isSubSignature(mt1, mt2)) {
+                        continue outer;
+                    }
+                }
+                mostSpecific = mostSpecific.prepend(msym1);
+            }
+            if (mostSpecific.isEmpty()) {
+                return null;
+            }
+
+
+            //pick return types - this is done in two phases: (i) first, the most
+            //specific return type is chosen using strict subtyping; if this fails,
+            //a second attempt is made using return type substitutability (see JLS 8.4.5)
+            boolean phase2 = false;
+            Symbol bestSoFar = null;
+            while (bestSoFar == null) {
+                outer: for (Symbol msym1 : mostSpecific) {
+                    Type mt1 = memberType(origin.type, msym1);
+                    for (Symbol msym2 : methodSyms) {
+                        Type mt2 = memberType(origin.type, msym2);
+                        if (phase2 ?
+                                !returnTypeSubstitutable(mt1, mt2) :
+                                !isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
+                            continue outer;
+                        }
+                    }
+                    bestSoFar = msym1;
+                }
+                if (phase2) {
+                    break;
+                } else {
+                    phase2 = true;
+                }
+            }
+            if (bestSoFar == null) return null;
+
+            //merge thrown types - form the intersection of all the thrown types in
+            //all the signatures in the list
+            List<Type> thrown = null;
+            for (Symbol msym1 : methodSyms) {
+                Type mt1 = memberType(origin.type, msym1);
+                thrown = (thrown == null) ?
+                    mt1.getThrownTypes() :
+                    chk.intersect(mt1.getThrownTypes(), thrown);
+            }
+
+            final List<Type> thrown1 = thrown;
+            return new FunctionDescriptor(bestSoFar) {
+                @Override
+                public Type getType(Type origin) {
+                    Type mt = memberType(origin, getSymbol());
+                    return new MethodType(mt.getParameterTypes(), mt.getReturnType(), thrown1, syms.methodClass);
+                }
+            };
+        }
+
+        boolean isSubtypeInternal(Type s, Type t) {
+            return (s.isPrimitive() && t.isPrimitive()) ?
+                    isSameType(t, s) :
+                    isSubtype(s, t);
+        }
+
+        FunctionDescriptorLookupError failure(String msg, Object... args) {
+            return failure(diags.fragment(msg, args));
+        }
+
+        FunctionDescriptorLookupError failure(JCDiagnostic diag) {
+            return functionDescriptorLookupError.setMessage(diag);
+        }
+    }
+
+    private DescriptorCache descCache = new DescriptorCache();
+
+    /**
+     * Find the method descriptor associated to this class symbol - if the
+     * symbol 'origin' is not a functional interface, an exception is thrown.
+     */
+    public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
+        return descCache.get(origin).getSymbol();
+    }
+
+    /**
+     * Find the type of the method descriptor associated to this class symbol -
+     * if the symbol 'origin' is not a functional interface, an exception is thrown.
+     */
+    public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
+        return descCache.get(origin.tsym).getType(origin);
+    }
+
+    /**
+     * Is given type a functional interface?
+     */
+    public boolean isFunctionalInterface(TypeSymbol tsym) {
+        try {
+            findDescriptorSymbol(tsym);
+            return true;
+        } catch (FunctionDescriptorLookupError ex) {
+            return false;
+        }
+    }
+    // </editor-fold>
+
     // <editor-fold defaultstate="collapsed" desc="isSubtype">
     /**
      * Is t an unchecked subtype of s?
@@ -510,7 +803,7 @@
                     return false;
                 }
 
-                t.hibounds = t.hibounds.prepend(s);
+                t.addBound(InferenceBound.UPPER, s, Types.this);
                 return true;
             }
 
@@ -578,7 +871,7 @@
                 undet.qtype == s ||
                 s.tag == ERROR ||
                 s.tag == BOT) return true;
-            undet.lobounds = undet.lobounds.prepend(s);
+            undet.addBound(InferenceBound.LOWER, s, this);
             return true;
         }
         default:
@@ -723,7 +1016,7 @@
                 if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
                     return true;
 
-                t.eq = t.eq.prepend(s);
+                t.addBound(InferenceBound.EQ, s, Types.this);
 
                 return true;
             }
@@ -735,19 +1028,6 @@
         };
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="fromUnknownFun">
-    /**
-     * A mapping that turns all unknown types in this type to fresh
-     * unknown variables.
-     */
-    public Mapping fromUnknownFun = new Mapping("fromUnknownFun") {
-            public Type apply(Type t) {
-                if (t.tag == UNKNOWN) return new UndetVar(t);
-                else return t.map(this);
-            }
-        };
-    // </editor-fold>
-
     // <editor-fold defaultstate="collapsed" desc="Contains Type">
     public boolean containedBy(Type t, Type s) {
         switch (t.tag) {
@@ -759,12 +1039,12 @@
                     case UNBOUND: //similar to ? extends Object
                     case EXTENDS: {
                         Type bound = upperBound(s);
-                        undetvar.hibounds = undetvar.hibounds.prepend(bound);
+                        undetvar.addBound(InferenceBound.UPPER, bound, this);
                         break;
                     }
                     case SUPER: {
                         Type bound = lowerBound(s);
-                        undetvar.lobounds = undetvar.lobounds.prepend(bound);
+                        undetvar.addBound(InferenceBound.LOWER, bound, this);
                         break;
                     }
                 }
@@ -1227,7 +1507,10 @@
      * Returns the lower bounds of the formals of a method.
      */
     public List<Type> lowerBoundArgtypes(Type t) {
-        return map(t.getParameterTypes(), lowerBoundMapping);
+        return lowerBounds(t.getParameterTypes());
+    }
+    public List<Type> lowerBounds(List<Type> ts) {
+        return map(ts, lowerBoundMapping);
     }
     private final Mapping lowerBoundMapping = new Mapping("lowerBound") {
             public Type apply(Type t) {
@@ -2019,6 +2302,15 @@
             hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
     }
 
+    public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
+        for (Scope.Entry e = syms.objectType.tsym.members().lookup(msym.name) ; e.scope != null ; e = e.next()) {
+            if (msym.overrides(e.sym, origin, Types.this, true)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     // <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
     class ImplementationCache {
 
@@ -3166,6 +3458,14 @@
         }
         return Type.noType;
     }
+
+    /**
+     * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
+     */
+    public Type unboxedTypeOrType(Type t) {
+        Type unboxedType = unboxedType(t);
+        return unboxedType.tag == NONE ? t : unboxedType;
+    }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Capture conversion">
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java	Thu Oct 11 17:00:54 2012 -0700
@@ -514,22 +514,6 @@
                       expectedType);
             fatalError = true;
         }
-
-        // validate that all other elements of containing type has defaults
-        scope = targetContainerType.tsym.members();
-        error = false;
-        for(Symbol elm : scope.getElements()) {
-            if (elm.name != names.value &&
-                elm.kind == Kinds.MTH &&
-                ((MethodSymbol)elm).defaultValue == null) {
-                log.error(pos,
-                          "invalid.containedby.annotation.elem.nondefault",
-                          targetContainerType,
-                          elm);
-                containerValueSymbol = null;
-                error = true;
-            }
-        }
         if (error) {
             fatalError = true;
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Oct 11 17:00:54 2012 -0700
@@ -25,12 +25,10 @@
 
 package com.sun.tools.javac.comp;
 
-import java.util.*;
-import java.util.Set;
-import javax.lang.model.element.ElementKind;
-import javax.tools.JavaFileObject;
-
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.util.*;
@@ -45,10 +43,16 @@
 import com.sun.tools.javac.comp.Check.CheckContext;
 
 import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.source.tree.MemberSelectTree;
 import com.sun.source.tree.TreeVisitor;
 import com.sun.source.util.SimpleTreeVisitor;
 
+import java.util.*;
+import java.util.Set;
+import javax.lang.model.element.ElementKind;
+import javax.tools.JavaFileObject;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
 import static com.sun.tools.javac.code.Flags.BLOCK;
@@ -80,7 +84,9 @@
     final Symtab syms;
     final Resolve rs;
     final Infer infer;
+    final DeferredAttr deferredAttr;
     final Check chk;
+    final Flow flow;
     final MemberEnter memberEnter;
     final TreeMaker make;
     final ConstFold cfolder;
@@ -106,10 +112,12 @@
         syms = Symtab.instance(context);
         rs = Resolve.instance(context);
         chk = Check.instance(context);
+        flow = Flow.instance(context);
         memberEnter = MemberEnter.instance(context);
         make = TreeMaker.instance(context);
         enter = Enter.instance(context);
         infer = Infer.instance(context);
+        deferredAttr = DeferredAttr.instance(context);
         cfolder = ConstFold.instance(context);
         target = Target.instance(context);
         types = Types.instance(context);
@@ -127,23 +135,31 @@
         allowCovariantReturns = source.allowCovariantReturns();
         allowAnonOuterThis = source.allowAnonOuterThis();
         allowStringsInSwitch = source.allowStringsInSwitch();
+        allowPoly = source.allowPoly() && options.isSet("allowPoly");
+        allowLambda = source.allowLambda();
         sourceName = source.name;
         relax = (options.isSet("-retrofit") ||
                  options.isSet("-relax"));
         findDiamonds = options.get("findDiamond") != null &&
                  source.allowDiamond();
         useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
+        identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false);
 
         statInfo = new ResultInfo(NIL, Type.noType);
         varInfo = new ResultInfo(VAR, Type.noType);
         unknownExprInfo = new ResultInfo(VAL, Type.noType);
         unknownTypeInfo = new ResultInfo(TYP, Type.noType);
+        recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
     }
 
     /** Switch: relax some constraints for retrofit mode.
      */
     boolean relax;
 
+    /** Switch: support target-typing inference
+     */
+    boolean allowPoly;
+
     /** Switch: support generics?
      */
     boolean allowGenerics;
@@ -164,6 +180,10 @@
      */
     boolean allowCovariantReturns;
 
+    /** Switch: support lambda expressions ?
+     */
+    boolean allowLambda;
+
     /** Switch: allow references to surrounding object from anonymous
      * objects during constructor call?
      */
@@ -186,6 +206,12 @@
     boolean useBeforeDeclarationWarning;
 
     /**
+     * Switch: generate warnings whenever an anonymous inner class that is convertible
+     * to a lambda expression is found
+     */
+    boolean identifyLambdaCandidate;
+
+    /**
      * Switch: allow strings in switch?
      */
     boolean allowStringsInSwitch;
@@ -207,15 +233,29 @@
      *  @param ownkind  The computed kind of the tree
      *  @param resultInfo  The expected result of the tree
      */
-    Type check(JCTree tree, Type owntype, int ownkind, ResultInfo resultInfo) {
+    Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) {
+        InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();
+        Type owntype = found;
         if (owntype.tag != ERROR && resultInfo.pt.tag != METHOD && resultInfo.pt.tag != FORALL) {
-            if ((ownkind & ~resultInfo.pkind) == 0) {
-                owntype = resultInfo.check(tree, owntype);
+            if (inferenceContext.free(found)) {
+                inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() {
+                    @Override
+                    public void typesInferred(InferenceContext inferenceContext) {
+                        ResultInfo pendingResult =
+                                    resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
+                        check(tree, inferenceContext.asInstType(found, types), ownkind, pendingResult);
+                    }
+                });
+                return tree.type = resultInfo.pt;
             } else {
-                log.error(tree.pos(), "unexpected.type",
-                          kindNames(resultInfo.pkind),
-                          kindName(ownkind));
-                owntype = types.createErrorType(owntype);
+                if ((ownkind & ~resultInfo.pkind) == 0) {
+                    owntype = resultInfo.check(tree, owntype);
+                } else {
+                    log.error(tree.pos(), "unexpected.type",
+                            kindNames(resultInfo.pkind),
+                            kindName(ownkind));
+                    owntype = types.createErrorType(owntype);
+                }
             }
         }
         tree.type = owntype;
@@ -262,6 +302,9 @@
                 case CLASSDEF:
                     //class def is always an owner
                     return ((JCClassDecl)env.tree).sym;
+                case LAMBDA:
+                    //a lambda is an owner - return a fresh synthetic method symbol
+                    return new MethodSymbol(0, names.empty, null, syms.methodClass);
                 case BLOCK:
                     //static/instance init blocks are owner
                     Symbol blockSym = env.info.scope.owner;
@@ -297,8 +340,6 @@
             } else {
                 log.error(pos, "cant.assign.val.to.final.var", v);
             }
-        } else if ((v.flags() & EFFECTIVELY_FINAL) != 0) {
-            v.flags_field &= ~EFFECTIVELY_FINAL;
         }
     }
 
@@ -431,14 +472,38 @@
         static final long serialVersionUID = -6924771130405446405L;
         private Env<AttrContext> env;
         private BreakAttr(Env<AttrContext> env) {
-            this.env = env;
+            this.env = copyEnv(env);
+        }
+
+        private Env<AttrContext> copyEnv(Env<AttrContext> env) {
+            Env<AttrContext> newEnv =
+                    env.dup(env.tree, env.info.dup(copyScope(env.info.scope)));
+            if (newEnv.outer != null) {
+                newEnv.outer = copyEnv(newEnv.outer);
+            }
+            return newEnv;
+        }
+
+        private Scope copyScope(Scope sc) {
+            Scope newScope = new Scope(sc.owner);
+            List<Symbol> elemsList = List.nil();
+            while (sc != null) {
+                for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) {
+                    elemsList = elemsList.prepend(e.sym);
+                }
+                sc = sc.next;
+            }
+            for (Symbol s : elemsList) {
+                newScope.enter(s);
+            }
+            return newScope;
         }
     }
 
     class ResultInfo {
-        int pkind;
-        Type pt;
-        CheckContext checkContext;
+        final int pkind;
+        final Type pt;
+        final CheckContext checkContext;
 
         ResultInfo(int pkind, Type pt) {
             this(pkind, pt, chk.basicHandler);
@@ -450,15 +515,45 @@
             this.checkContext = checkContext;
         }
 
-        protected Type check(DiagnosticPosition pos, Type found) {
+        protected Type check(final DiagnosticPosition pos, final Type found) {
             return chk.checkType(pos, found, pt, checkContext);
         }
+
+        protected ResultInfo dup(Type newPt) {
+            return new ResultInfo(pkind, newPt, checkContext);
+        }
     }
 
-    private final ResultInfo statInfo;
-    private final ResultInfo varInfo;
-    private final ResultInfo unknownExprInfo;
-    private final ResultInfo unknownTypeInfo;
+    class RecoveryInfo extends ResultInfo {
+
+        public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) {
+            super(Kinds.VAL, Type.recoveryType, new Check.NestedCheckContext(chk.basicHandler) {
+                @Override
+                public DeferredAttr.DeferredAttrContext deferredAttrContext() {
+                    return deferredAttrContext;
+                }
+                @Override
+                public boolean compatible(Type found, Type req, Warner warn) {
+                    return true;
+                }
+                @Override
+                public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                    //do nothing
+                }
+            });
+        }
+
+        @Override
+        protected Type check(DiagnosticPosition pos, Type found) {
+            return chk.checkNonVoid(pos, super.check(pos, found));
+        }
+    }
+
+    final ResultInfo statInfo;
+    final ResultInfo varInfo;
+    final ResultInfo unknownExprInfo;
+    final ResultInfo unknownTypeInfo;
+    final ResultInfo recoveryInfo;
 
     Type pt() {
         return resultInfo.pt;
@@ -491,7 +586,7 @@
      *  @param env     The environment visitor argument.
      *  @param resultInfo   The result info visitor argument.
      */
-    private Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
+    Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
         Env<AttrContext> prevEnv = this.env;
         ResultInfo prevResult = this.resultInfo;
         try {
@@ -563,9 +658,12 @@
      */
     List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) {
         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(attribExpr(l.head, env, Infer.anyPoly))));
+        for (JCExpression arg : trees) {
+            Type argtype = allowPoly && TreeInfo.isPoly(arg, env.tree) ?
+                    deferredAttr.new DeferredType(arg, env) :
+                    chk.checkNonVoid(arg, attribExpr(arg, env, Infer.anyPoly));
+            argtypes.append(argtype);
+        }
         return argtypes.toList();
     }
 
@@ -934,7 +1032,10 @@
             chk.checkDeprecatedAnnotation(tree.pos(), v);
 
             if (tree.init != null) {
-                if ((v.flags_field & FINAL) != 0 && !tree.init.hasTag(NEWCLASS)) {
+                if ((v.flags_field & FINAL) != 0 &&
+                        !tree.init.hasTag(NEWCLASS) &&
+                        !tree.init.hasTag(LAMBDA) &&
+                        !tree.init.hasTag(REFERENCE)) {
                     // In this case, `v' is final.  Ensure that it's initializer is
                     // evaluated.
                     v.getConstValue(); // ensure initializer is evaluated
@@ -979,8 +1080,11 @@
             // Create a new local environment with a local scope.
             Env<AttrContext> localEnv =
                 env.dup(tree, env.info.dup(env.info.scope.dup()));
-            attribStats(tree.stats, localEnv);
-            localEnv.info.scope.leave();
+            try {
+                attribStats(tree.stats, localEnv);
+            } finally {
+                localEnv.info.scope.leave();
+            }
         }
         result = null;
     }
@@ -1000,43 +1104,51 @@
     public void visitForLoop(JCForLoop tree) {
         Env<AttrContext> loopEnv =
             env.dup(env.tree, env.info.dup(env.info.scope.dup()));
-        attribStats(tree.init, loopEnv);
-        if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType);
-        loopEnv.tree = tree; // before, we were not in loop!
-        attribStats(tree.step, loopEnv);
-        attribStat(tree.body, loopEnv);
-        loopEnv.info.scope.leave();
-        result = null;
+        try {
+            attribStats(tree.init, loopEnv);
+            if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType);
+            loopEnv.tree = tree; // before, we were not in loop!
+            attribStats(tree.step, loopEnv);
+            attribStat(tree.body, loopEnv);
+            result = null;
+        }
+        finally {
+            loopEnv.info.scope.leave();
+        }
     }
 
     public void visitForeachLoop(JCEnhancedForLoop tree) {
         Env<AttrContext> loopEnv =
             env.dup(env.tree, env.info.dup(env.info.scope.dup()));
-        attribStat(tree.var, loopEnv);
-        Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));
-        chk.checkNonVoid(tree.pos(), exprType);
-        Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
-        if (elemtype == null) {
-            // or perhaps expr implements Iterable<T>?
-            Type base = types.asSuper(exprType, syms.iterableType.tsym);
-            if (base == null) {
-                log.error(tree.expr.pos(),
-                        "foreach.not.applicable.to.type",
-                        exprType,
-                        diags.fragment("type.req.array.or.iterable"));
-                elemtype = types.createErrorType(exprType);
-            } else {
-                List<Type> iterableParams = base.allparams();
-                elemtype = iterableParams.isEmpty()
-                    ? syms.objectType
-                    : types.upperBound(iterableParams.head);
+        try {
+            attribStat(tree.var, loopEnv);
+            Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv));
+            chk.checkNonVoid(tree.pos(), exprType);
+            Type elemtype = types.elemtype(exprType); // perhaps expr is an array?
+            if (elemtype == null) {
+                // or perhaps expr implements Iterable<T>?
+                Type base = types.asSuper(exprType, syms.iterableType.tsym);
+                if (base == null) {
+                    log.error(tree.expr.pos(),
+                            "foreach.not.applicable.to.type",
+                            exprType,
+                            diags.fragment("type.req.array.or.iterable"));
+                    elemtype = types.createErrorType(exprType);
+                } else {
+                    List<Type> iterableParams = base.allparams();
+                    elemtype = iterableParams.isEmpty()
+                        ? syms.objectType
+                        : types.upperBound(iterableParams.head);
+                }
             }
+            chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
+            loopEnv.tree = tree; // before, we were not in loop!
+            attribStat(tree.body, loopEnv);
+            result = null;
         }
-        chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type);
-        loopEnv.tree = tree; // before, we were not in loop!
-        attribStat(tree.body, loopEnv);
-        loopEnv.info.scope.leave();
-        result = null;
+        finally {
+            loopEnv.info.scope.leave();
+        }
     }
 
     public void visitLabelled(JCLabeledStatement tree) {
@@ -1062,61 +1174,69 @@
         Env<AttrContext> switchEnv =
             env.dup(tree, env.info.dup(env.info.scope.dup()));
 
-        boolean enumSwitch =
-            allowEnums &&
-            (seltype.tsym.flags() & Flags.ENUM) != 0;
-        boolean stringSwitch = false;
-        if (types.isSameType(seltype, syms.stringType)) {
-            if (allowStringsInSwitch) {
-                stringSwitch = true;
-            } else {
-                log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName);
+        try {
+
+            boolean enumSwitch =
+                allowEnums &&
+                (seltype.tsym.flags() & Flags.ENUM) != 0;
+            boolean stringSwitch = false;
+            if (types.isSameType(seltype, syms.stringType)) {
+                if (allowStringsInSwitch) {
+                    stringSwitch = true;
+                } else {
+                    log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName);
+                }
             }
+            if (!enumSwitch && !stringSwitch)
+                seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
+
+            // Attribute all cases and
+            // check that there are no duplicate case labels or default clauses.
+            Set<Object> labels = new HashSet<Object>(); // The set of case labels.
+            boolean hasDefault = false;      // Is there a default label?
+            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
+                JCCase c = l.head;
+                Env<AttrContext> caseEnv =
+                    switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
+                try {
+                    if (c.pat != null) {
+                        if (enumSwitch) {
+                            Symbol sym = enumConstant(c.pat, seltype);
+                            if (sym == null) {
+                                log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
+                            } else if (!labels.add(sym)) {
+                                log.error(c.pos(), "duplicate.case.label");
+                            }
+                        } else {
+                            Type pattype = attribExpr(c.pat, switchEnv, seltype);
+                            if (pattype.tag != ERROR) {
+                                if (pattype.constValue() == null) {
+                                    log.error(c.pat.pos(),
+                                              (stringSwitch ? "string.const.req" : "const.expr.req"));
+                                } else if (labels.contains(pattype.constValue())) {
+                                    log.error(c.pos(), "duplicate.case.label");
+                                } else {
+                                    labels.add(pattype.constValue());
+                                }
+                            }
+                        }
+                    } else if (hasDefault) {
+                        log.error(c.pos(), "duplicate.default.label");
+                    } else {
+                        hasDefault = true;
+                    }
+                    attribStats(c.stats, caseEnv);
+                } finally {
+                    caseEnv.info.scope.leave();
+                    addVars(c.stats, switchEnv.info.scope);
+                }
+            }
+
+            result = null;
         }
-        if (!enumSwitch && !stringSwitch)
-            seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType);
-
-        // Attribute all cases and
-        // check that there are no duplicate case labels or default clauses.
-        Set<Object> labels = new HashSet<Object>(); // The set of case labels.
-        boolean hasDefault = false;      // Is there a default label?
-        for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
-            JCCase c = l.head;
-            Env<AttrContext> caseEnv =
-                switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
-            if (c.pat != null) {
-                if (enumSwitch) {
-                    Symbol sym = enumConstant(c.pat, seltype);
-                    if (sym == null) {
-                        log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
-                    } else if (!labels.add(sym)) {
-                        log.error(c.pos(), "duplicate.case.label");
-                    }
-                } else {
-                    Type pattype = attribExpr(c.pat, switchEnv, seltype);
-                    if (pattype.tag != ERROR) {
-                        if (pattype.constValue() == null) {
-                            log.error(c.pat.pos(),
-                                      (stringSwitch ? "string.const.req" : "const.expr.req"));
-                        } else if (labels.contains(pattype.constValue())) {
-                            log.error(c.pos(), "duplicate.case.label");
-                        } else {
-                            labels.add(pattype.constValue());
-                        }
-                    }
-                }
-            } else if (hasDefault) {
-                log.error(c.pos(), "duplicate.default.label");
-            } else {
-                hasDefault = true;
-            }
-            attribStats(c.stats, caseEnv);
-            caseEnv.info.scope.leave();
-            addVars(c.stats, switchEnv.info.scope);
+        finally {
+            switchEnv.info.scope.leave();
         }
-
-        switchEnv.info.scope.leave();
-        result = null;
     }
     // where
         /** Add any variables defined in stats to the switch scope. */
@@ -1158,63 +1278,72 @@
     public void visitTry(JCTry tree) {
         // Create a new local environment with a local
         Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup()));
-        boolean isTryWithResource = tree.resources.nonEmpty();
-        // Create a nested environment for attributing the try block if needed
-        Env<AttrContext> tryEnv = isTryWithResource ?
-            env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) :
-            localEnv;
-        // Attribute resource declarations
-        for (JCTree resource : tree.resources) {
-            CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) {
-                @Override
-                public void report(DiagnosticPosition pos, JCDiagnostic details) {
-                    chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details));
+        try {
+            boolean isTryWithResource = tree.resources.nonEmpty();
+            // Create a nested environment for attributing the try block if needed
+            Env<AttrContext> tryEnv = isTryWithResource ?
+                env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) :
+                localEnv;
+            try {
+                // Attribute resource declarations
+                for (JCTree resource : tree.resources) {
+                    CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) {
+                        @Override
+                        public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                            chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details));
+                        }
+                    };
+                    ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext);
+                    if (resource.hasTag(VARDEF)) {
+                        attribStat(resource, tryEnv);
+                        twrResult.check(resource, resource.type);
+
+                        //check that resource type cannot throw InterruptedException
+                        checkAutoCloseable(resource.pos(), localEnv, resource.type);
+
+                        VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource);
+                        var.setData(ElementKind.RESOURCE_VARIABLE);
+                    } else {
+                        attribTree(resource, tryEnv, twrResult);
+                    }
                 }
-            };
-            ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext);
-            if (resource.hasTag(VARDEF)) {
-                attribStat(resource, tryEnv);
-                twrResult.check(resource, resource.type);
-
-                //check that resource type cannot throw InterruptedException
-                checkAutoCloseable(resource.pos(), localEnv, resource.type);
-
-                VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource);
-                var.setData(ElementKind.RESOURCE_VARIABLE);
-            } else {
-                attribTree(resource, tryEnv, twrResult);
+                // Attribute body
+                attribStat(tree.body, tryEnv);
+            } finally {
+                if (isTryWithResource)
+                    tryEnv.info.scope.leave();
             }
+
+            // Attribute catch clauses
+            for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
+                JCCatch c = l.head;
+                Env<AttrContext> catchEnv =
+                    localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup()));
+                try {
+                    Type ctype = attribStat(c.param, catchEnv);
+                    if (TreeInfo.isMultiCatch(c)) {
+                        //multi-catch parameter is implicitly marked as final
+                        c.param.sym.flags_field |= FINAL | UNION;
+                    }
+                    if (c.param.sym.kind == Kinds.VAR) {
+                        c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
+                    }
+                    chk.checkType(c.param.vartype.pos(),
+                                  chk.checkClassType(c.param.vartype.pos(), ctype),
+                                  syms.throwableType);
+                    attribStat(c.body, catchEnv);
+                } finally {
+                    catchEnv.info.scope.leave();
+                }
+            }
+
+            // Attribute finalizer
+            if (tree.finalizer != null) attribStat(tree.finalizer, localEnv);
+            result = null;
         }
-        // Attribute body
-        attribStat(tree.body, tryEnv);
-        if (isTryWithResource)
-            tryEnv.info.scope.leave();
-
-        // Attribute catch clauses
-        for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
-            JCCatch c = l.head;
-            Env<AttrContext> catchEnv =
-                localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup()));
-            Type ctype = attribStat(c.param, catchEnv);
-            if (TreeInfo.isMultiCatch(c)) {
-                //multi-catch parameter is implicitly marked as final
-                c.param.sym.flags_field |= FINAL | UNION;
-            }
-            if (c.param.sym.kind == Kinds.VAR) {
-                c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
-            }
-            chk.checkType(c.param.vartype.pos(),
-                          chk.checkClassType(c.param.vartype.pos(), ctype),
-                          syms.throwableType);
-            attribStat(c.body, catchEnv);
-            catchEnv.info.scope.leave();
+        finally {
+            localEnv.info.scope.leave();
         }
-
-        // Attribute finalizer
-        if (tree.finalizer != null) attribStat(tree.finalizer, localEnv);
-
-        localEnv.info.scope.leave();
-        result = null;
     }
 
     void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) {
@@ -1222,10 +1351,10 @@
             types.asSuper(resource, syms.autoCloseableType.tsym) != null &&
             !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself
             Symbol close = syms.noSymbol;
-            boolean prevDeferDiags = log.deferDiagnostics;
+            Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
             Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
             try {
-                log.deferDiagnostics = true;
+                log.deferAll();
                 log.deferredDiagnostics = ListBuffer.lb();
                 close = rs.resolveQualifiedMethod(pos,
                         env,
@@ -1235,7 +1364,7 @@
                         List.<Type>nil());
             }
             finally {
-                log.deferDiagnostics = prevDeferDiags;
+                log.deferredDiagFilter = prevDeferDiagsFilter;
                 log.deferredDiagnostics = prevDeferredDiags;
             }
             if (close.kind == MTH &&
@@ -1248,50 +1377,71 @@
     }
 
     public void visitConditional(JCConditional tree) {
-        attribExpr(tree.cond, env, syms.booleanType);
-        attribExpr(tree.truepart, env);
-        attribExpr(tree.falsepart, env);
-        result = check(tree,
-                       capture(condType(tree.pos(), tree.cond.type,
-                                        tree.truepart.type, tree.falsepart.type)),
-                       VAL, resultInfo);
+        Type condtype = attribExpr(tree.cond, env, syms.booleanType);
+
+        boolean standaloneConditional = !allowPoly ||
+                pt().tag == NONE && pt() != Type.recoveryType ||
+                isBooleanOrNumeric(env, tree);
+
+        if (!standaloneConditional && resultInfo.pt.tag == VOID) {
+            //cannot get here (i.e. it means we are returning from void method - which is already an error)
+            result = tree.type = types.createErrorType(resultInfo.pt);
+            return;
+        }
+
+        ResultInfo condInfo = standaloneConditional ?
+                unknownExprInfo :
+                new ResultInfo(VAL, pt(), new Check.NestedCheckContext(resultInfo.checkContext) {
+                    //this will use enclosing check context to check compatibility of
+                    //subexpression against target type; if we are in a method check context,
+                    //depending on whether boxing is allowed, we could have incompatibilities
+                    @Override
+                    public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                        enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details));
+                    }
+                });
+
+        Type truetype = attribTree(tree.truepart, env, condInfo);
+        Type falsetype = attribTree(tree.falsepart, env, condInfo);
+
+        Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt();
+        if (condtype.constValue() != null &&
+                truetype.constValue() != null &&
+                falsetype.constValue() != null) {
+            //constant folding
+            owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype);
+        }
+        result = check(tree, owntype, VAL, resultInfo);
     }
     //where
+        @SuppressWarnings("fallthrough")
+        private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) {
+            switch (tree.getTag()) {
+                case LITERAL: return ((JCLiteral)tree).typetag < CLASS;
+                case LAMBDA: case REFERENCE: return false;
+                case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr);
+                case CONDEXPR:
+                    JCConditional condTree = (JCConditional)tree;
+                    return isBooleanOrNumeric(env, condTree.truepart) &&
+                            isBooleanOrNumeric(env, condTree.falsepart);
+                default:
+                    Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
+                    speculativeType = types.unboxedTypeOrType(speculativeType);
+                    return speculativeType.tag <= BOOLEAN;
+            }
+        }
+
         /** Compute the type of a conditional expression, after
-         *  checking that it exists. See Spec 15.25.
-         *
-         *  @param pos      The source position to be used for
-         *                  error diagnostics.
-         *  @param condtype The type of the expression's condition.
-         *  @param thentype The type of the expression's then-part.
-         *  @param elsetype The type of the expression's else-part.
-         */
-        private Type condType(DiagnosticPosition pos,
-                              Type condtype,
-                              Type thentype,
-                              Type elsetype) {
-            Type ctype = condType1(pos, condtype, thentype, elsetype);
-
-            // If condition and both arms are numeric constants,
-            // evaluate at compile-time.
-            return ((condtype.constValue() != null) &&
-                    (thentype.constValue() != null) &&
-                    (elsetype.constValue() != null))
-                ? cfolder.coerce(condtype.isTrue()?thentype:elsetype, ctype)
-                : ctype;
-        }
-        /** Compute the type of a conditional expression, after
-         *  checking that it exists.  Does not take into
+         *  checking that it exists.  See JLS 15.25. Does not take into
          *  account the special case where condition and both arms
          *  are constants.
          *
          *  @param pos      The source position to be used for error
          *                  diagnostics.
-         *  @param condtype The type of the expression's condition.
          *  @param thentype The type of the expression's then-part.
          *  @param elsetype The type of the expression's else-part.
          */
-        private Type condType1(DiagnosticPosition pos, Type condtype,
+        private Type condType(DiagnosticPosition pos,
                                Type thentype, Type elsetype) {
             // If same type, that is the result
             if (types.isSameType(thentype, elsetype))
@@ -1399,37 +1549,38 @@
             LOOP:
             while (env1 != null) {
                 switch (env1.tree.getTag()) {
-                case LABELLED:
-                    JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
-                    if (label == labelled.label) {
-                        // If jump is a continue, check that target is a loop.
-                        if (tag == CONTINUE) {
-                            if (!labelled.body.hasTag(DOLOOP) &&
-                                !labelled.body.hasTag(WHILELOOP) &&
-                                !labelled.body.hasTag(FORLOOP) &&
-                                !labelled.body.hasTag(FOREACHLOOP))
-                                log.error(pos, "not.loop.label", label);
-                            // Found labelled statement target, now go inwards
-                            // to next non-labelled tree.
-                            return TreeInfo.referencedStatement(labelled);
-                        } else {
-                            return labelled;
+                    case LABELLED:
+                        JCLabeledStatement labelled = (JCLabeledStatement)env1.tree;
+                        if (label == labelled.label) {
+                            // If jump is a continue, check that target is a loop.
+                            if (tag == CONTINUE) {
+                                if (!labelled.body.hasTag(DOLOOP) &&
+                                        !labelled.body.hasTag(WHILELOOP) &&
+                                        !labelled.body.hasTag(FORLOOP) &&
+                                        !labelled.body.hasTag(FOREACHLOOP))
+                                    log.error(pos, "not.loop.label", label);
+                                // Found labelled statement target, now go inwards
+                                // to next non-labelled tree.
+                                return TreeInfo.referencedStatement(labelled);
+                            } else {
+                                return labelled;
+                            }
                         }
-                    }
-                    break;
-                case DOLOOP:
-                case WHILELOOP:
-                case FORLOOP:
-                case FOREACHLOOP:
-                    if (label == null) return env1.tree;
-                    break;
-                case SWITCH:
-                    if (label == null && tag == BREAK) return env1.tree;
-                    break;
-                case METHODDEF:
-                case CLASSDEF:
-                    break LOOP;
-                default:
+                        break;
+                    case DOLOOP:
+                    case WHILELOOP:
+                    case FORLOOP:
+                    case FOREACHLOOP:
+                        if (label == null) return env1.tree;
+                        break;
+                    case SWITCH:
+                        if (label == null && tag == BREAK) return env1.tree;
+                        break;
+                    case LAMBDA:
+                    case METHODDEF:
+                    case CLASSDEF:
+                        break LOOP;
+                    default:
                 }
                 env1 = env1.next;
             }
@@ -1445,22 +1596,19 @@
     public void visitReturn(JCReturn tree) {
         // 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) {
+        if (env.info.returnResult == null) {
             log.error(tree.pos(), "ret.outside.meth");
-
         } else {
             // Attribute return expression, if it exists, and check that
             // it conforms to result type of enclosing method.
-            Symbol m = env.enclMethod.sym;
-            if (m.type.getReturnType().tag == VOID) {
-                if (tree.expr != null)
+            if (tree.expr != null) {
+                if (env.info.returnResult.pt.tag == VOID) {
                     log.error(tree.expr.pos(),
                               "cant.ret.val.from.meth.decl.void");
-            } else if (tree.expr == null) {
+                }
+                attribTree(tree.expr, env, env.info.returnResult);
+            } else if (env.info.returnResult.pt.tag != VOID) {
                 log.error(tree.pos(), "missing.ret.val");
-            } else {
-                attribExpr(tree.expr, env, m.type.getReturnType());
             }
         }
         result = null;
@@ -1562,7 +1710,7 @@
                     // current instance (JLS ???).
                     boolean selectSuperPrev = localEnv.info.selectSuper;
                     localEnv.info.selectSuper = true;
-                    localEnv.info.varArgs = false;
+                    localEnv.info.pendingResolutionPhase = null;
                     Symbol sym = rs.resolveConstructor(
                         tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
                     localEnv.info.selectSuper = selectSuperPrev;
@@ -1573,8 +1721,7 @@
                     // ...and check that it is legal in the current context.
                     // (this will also set the tree's type)
                     Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
-                    checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt),
-                            tree.varargsElement != null);
+                    checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt));
                 }
                 // Otherwise, `site' is an error type and we do nothing
             }
@@ -1589,35 +1736,18 @@
             // whose formal argument types is exactly the list of actual
             // arguments (this will also set the method symbol).
             Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
-            localEnv.info.varArgs = false;
-            Type mtype = attribExpr(tree.meth, localEnv, mpt);
+            localEnv.info.pendingResolutionPhase = null;
+            Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(VAL, mpt, resultInfo.checkContext));
 
             // Compute the result type.
             Type restype = mtype.getReturnType();
             if (restype.tag == WILDCARD)
                 throw new AssertionError(mtype);
 
-            // as a special case, array.clone() has a result that is
-            // the same as static type of the array being cloned
-            if (tree.meth.hasTag(SELECT) &&
-                allowCovariantReturns &&
-                methName == names.clone &&
-                types.isArray(((JCFieldAccess) tree.meth).selected.type))
-                restype = ((JCFieldAccess) tree.meth).selected.type;
-
-            // as a special case, x.getClass() has type Class<? extends |X|>
-            if (allowGenerics &&
-                methName == names.getClass && tree.args.isEmpty()) {
-                Type qualifier = (tree.meth.hasTag(SELECT))
+            Type qualifier = (tree.meth.hasTag(SELECT))
                     ? ((JCFieldAccess) tree.meth).selected.type
                     : env.enclClass.sym.type;
-                restype = new
-                    ClassType(restype.getEnclosingType(),
-                              List.<Type>of(new WildcardType(types.erasure(qualifier),
-                                                               BoundKind.EXTENDS,
-                                                               syms.boundClass)),
-                              restype.tsym);
-            }
+            restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
 
             chk.checkRefTypes(tree.typeargs, typeargtypes);
 
@@ -1625,12 +1755,33 @@
             // current context.  Also, capture the return type
             result = check(tree, capture(restype), VAL, resultInfo);
 
-            if (localEnv.info.varArgs)
+            if (localEnv.info.lastResolveVarargs())
                 Assert.check(result.isErroneous() || tree.varargsElement != null);
         }
         chk.validate(tree.typeargs, localEnv);
     }
     //where
+        Type adjustMethodReturnType(Type qualifierType, Name methodName, List<Type> argtypes, Type restype) {
+            if (allowCovariantReturns &&
+                    methodName == names.clone &&
+                types.isArray(qualifierType)) {
+                // as a special case, array.clone() has a result that is
+                // the same as static type of the array being cloned
+                return qualifierType;
+            } else if (allowGenerics &&
+                    methodName == names.getClass &&
+                    argtypes.isEmpty()) {
+                // as a special case, x.getClass() has type Class<? extends |X|>
+                return new ClassType(restype.getEnclosingType(),
+                              List.<Type>of(new WildcardType(types.erasure(qualifierType),
+                                                               BoundKind.EXTENDS,
+                                                               syms.boundClass)),
+                              restype.tsym);
+            } else {
+                return restype;
+            }
+        }
+
         /** Check that given application node appears as first statement
          *  in a constructor call.
          *  @param tree   The application node
@@ -1652,11 +1803,11 @@
         /** Obtain a method type with given argument types.
          */
         Type newMethodTemplate(Type restype, List<Type> argtypes, List<Type> typeargtypes) {
-            MethodType mt = new MethodType(argtypes, restype, null, syms.methodClass);
+            MethodType mt = new MethodType(argtypes, restype, List.<Type>nil(), syms.methodClass);
             return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt);
         }
 
-    public void visitNewClass(JCNewClass tree) {
+    public void visitNewClass(final JCNewClass tree) {
         Type owntype = types.createErrorType(tree.type);
 
         // The local environment of a class creation is
@@ -1729,42 +1880,6 @@
         List<Type> argtypes = attribArgs(tree.args, localEnv);
         List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv);
 
-        if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) {
-            clazztype = attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes);
-            clazz.type = clazztype;
-        } else if (allowDiamondFinder &&
-                tree.def == null &&
-                !clazztype.isErroneous() &&
-                clazztype.getTypeArguments().nonEmpty() &&
-                findDiamonds) {
-            boolean prevDeferDiags = log.deferDiagnostics;
-            Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
-            Type inferred = null;
-            try {
-                //disable diamond-related diagnostics
-                log.deferDiagnostics = true;
-                log.deferredDiagnostics = ListBuffer.lb();
-                inferred = attribDiamond(localEnv,
-                        tree,
-                        clazztype,
-                        argtypes,
-                        typeargtypes);
-            }
-            finally {
-                log.deferDiagnostics = prevDeferDiags;
-                log.deferredDiagnostics = prevDeferredDiags;
-            }
-            if (inferred != null &&
-                    !inferred.isErroneous() &&
-                    inferred.tag == CLASS &&
-                    types.isAssignable(inferred, pt().tag == NONE ? clazztype : pt(), Warner.noWarnings)) {
-                String key = types.isSameType(clazztype, inferred) ?
-                    "diamond.redundant.args" :
-                    "diamond.redundant.args.1";
-                log.warning(tree.clazz.pos(), key, clazztype, inferred);
-            }
-        }
-
         // If we have made no mistakes in the class type...
         if (clazztype.tag == CLASS) {
             // Enums may not be instantiated except implicitly
@@ -1791,6 +1906,45 @@
                 // Error recovery: pretend no arguments were supplied.
                 argtypes = List.nil();
                 typeargtypes = List.nil();
+            } else if (TreeInfo.isDiamond(tree)) {
+                ClassType site = new ClassType(clazztype.getEnclosingType(),
+                            clazztype.tsym.type.getTypeArguments(),
+                            clazztype.tsym);
+
+                Env<AttrContext> diamondEnv = localEnv.dup(tree);
+                diamondEnv.info.selectSuper = cdef != null;
+                diamondEnv.info.pendingResolutionPhase = null;
+
+                //if the type of the instance creation expression is a class type
+                //apply method resolution inference (JLS 15.12.2.7). The return type
+                //of the resolved constructor will be a partially instantiated type
+                Symbol constructor = rs.resolveDiamond(tree.pos(),
+                            diamondEnv,
+                            site,
+                            argtypes,
+                            typeargtypes);
+                tree.constructor = constructor.baseSymbol();
+
+                final TypeSymbol csym = clazztype.tsym;
+                ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) {
+                    @Override
+                    public void report(DiagnosticPosition _unused, JCDiagnostic details) {
+                        enclosingContext.report(tree.clazz,
+                                diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", csym), details));
+                    }
+                });
+                Type constructorType = tree.constructorType = types.createErrorType(clazztype);
+                constructorType = checkId(tree, site,
+                        constructor,
+                        diamondEnv,
+                        diamondResult);
+
+                tree.clazz.type = types.createErrorType(clazztype);
+                if (!constructorType.isErroneous()) {
+                    tree.clazz.type = clazztype = constructorType.getReturnType();
+                    tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType);
+                }
+                clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true);
             }
 
             // Resolve the called constructor under the assumption
@@ -1802,20 +1956,19 @@
                 //order to avoid downstream failures
                 Env<AttrContext> rsEnv = localEnv.dup(tree);
                 rsEnv.info.selectSuper = cdef != null;
-                rsEnv.info.varArgs = false;
+                rsEnv.info.pendingResolutionPhase = null;
                 tree.constructor = rs.resolveConstructor(
                     tree.pos(), rsEnv, clazztype, argtypes, typeargtypes);
-                tree.constructorType = tree.constructor.type.isErroneous() ?
-                    syms.errType :
-                    checkConstructor(clazztype,
-                        tree.constructor,
-                        rsEnv,
-                        tree.args,
-                        argtypes,
-                        typeargtypes,
-                        rsEnv.info.varArgs);
-                if (rsEnv.info.varArgs)
-                    Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
+                if (cdef == null) { //do not check twice!
+                    tree.constructorType = checkId(tree,
+                            clazztype,
+                            tree.constructor,
+                            rsEnv,
+                            new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes)));
+                    if (rsEnv.info.lastResolveVarargs())
+                        Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
+                }
+                findDiamondIfNeeded(localEnv, tree, clazztype);
             }
 
             if (cdef != null) {
@@ -1861,6 +2014,8 @@
 
                 attribStat(cdef, localEnv);
 
+                checkLambdaCandidate(tree, cdef.sym, clazztype);
+
                 // If an outer instance is given,
                 // prefix it to the constructor arguments
                 // and delete it from the new expression
@@ -1872,24 +2027,15 @@
 
                 // Reassign clazztype and recompute constructor.
                 clazztype = cdef.sym.type;
-                boolean useVarargs = tree.varargsElement != null;
-                Symbol sym = rs.resolveConstructor(
-                    tree.pos(), localEnv, clazztype, argtypes,
-                    typeargtypes, true, useVarargs);
-                Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous());
+                Symbol sym = tree.constructor = rs.resolveConstructor(
+                    tree.pos(), localEnv, clazztype, argtypes, typeargtypes);
+                Assert.check(sym.kind < AMBIGUOUS);
                 tree.constructor = sym;
-                if (tree.constructor.kind > ERRONEOUS) {
-                    tree.constructorType =  syms.errType;
-                }
-                else {
-                    tree.constructorType = checkConstructor(clazztype,
-                            tree.constructor,
-                            localEnv,
-                            tree.args,
-                            argtypes,
-                            typeargtypes,
-                            useVarargs);
-                }
+                tree.constructorType = checkId(tree,
+                    clazztype,
+                    tree.constructor,
+                    localEnv,
+                    new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes)));
             }
 
             if (tree.constructor != null && tree.constructor.kind == MTH)
@@ -1898,57 +2044,58 @@
         result = check(tree, owntype, VAL, resultInfo);
         chk.validate(tree.typeargs, localEnv);
     }
-
-    Type attribDiamond(Env<AttrContext> env,
-                        final JCNewClass tree,
-                        final Type clazztype,
-                        List<Type> argtypes,
-                        List<Type> typeargtypes) {
-        if (clazztype.isErroneous() ||
-                clazztype.isInterface()) {
-            //if the type of the instance creation expression is erroneous,
-            //or if it's an interface, or if something prevented us to form a valid
-            //mapping, return the (possibly erroneous) type unchanged
-            return clazztype;
+    //where
+        void findDiamondIfNeeded(Env<AttrContext> env, JCNewClass tree, Type clazztype) {
+            if (tree.def == null &&
+                    !clazztype.isErroneous() &&
+                    clazztype.getTypeArguments().nonEmpty() &&
+                    findDiamonds) {
+                JCTypeApply ta = (JCTypeApply)tree.clazz;
+                List<JCExpression> prevTypeargs = ta.arguments;
+                try {
+                    //create a 'fake' diamond AST node by removing type-argument trees
+                    ta.arguments = List.nil();
+                    ResultInfo findDiamondResult = new ResultInfo(VAL,
+                            resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt());
+                    Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type;
+                    if (!inferred.isErroneous() &&
+                        types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) {
+                        String key = types.isSameType(clazztype, inferred) ?
+                            "diamond.redundant.args" :
+                            "diamond.redundant.args.1";
+                        log.warning(tree.clazz.pos(), key, clazztype, inferred);
+                    }
+                } finally {
+                    ta.arguments = prevTypeargs;
+                }
+            }
         }
 
-        //dup attribution environment and augment the set of inference variables
-        Env<AttrContext> localEnv = env.dup(tree);
-
-        ClassType site = new ClassType(clazztype.getEnclosingType(),
-                    clazztype.tsym.type.getTypeArguments(),
-                    clazztype.tsym);
-
-        //if the type of the instance creation expression is a class type
-        //apply method resolution inference (JLS 15.12.2.7). The return type
-        //of the resolved constructor will be a partially instantiated type
-        Symbol constructor = rs.resolveDiamond(tree.pos(),
-                    localEnv,
-                    site,
-                    argtypes,
-                    typeargtypes);
-
-        Type owntype = types.createErrorType(clazztype);
-        if (constructor.kind == MTH) {
-            ResultInfo diamondResult = new ResultInfo(VAL, resultInfo.pt, new Check.NestedCheckContext(resultInfo.checkContext) {
-                @Override
-                public void report(DiagnosticPosition pos, JCDiagnostic details) {
-                    enclosingContext.report(tree.clazz.pos(),
-                            diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), details));
+            private void checkLambdaCandidate(JCNewClass tree, ClassSymbol csym, Type clazztype) {
+                if (allowLambda &&
+                        identifyLambdaCandidate &&
+                        clazztype.tag == CLASS &&
+                        pt().tag != NONE &&
+                        types.isFunctionalInterface(clazztype.tsym)) {
+                    Symbol descriptor = types.findDescriptorSymbol(clazztype.tsym);
+                    int count = 0;
+                    boolean found = false;
+                    for (Symbol sym : csym.members().getElements()) {
+                        if ((sym.flags() & SYNTHETIC) != 0 ||
+                                sym.isConstructor()) continue;
+                        count++;
+                        if (sym.kind != MTH ||
+                                !sym.name.equals(descriptor.name)) continue;
+                        Type mtype = types.memberType(clazztype, sym);
+                        if (types.overrideEquivalent(mtype, types.memberType(clazztype, descriptor))) {
+                            found = true;
+                        }
+                    }
+                    if (found && count == 1) {
+                        log.note(tree.def, "potential.lambda.found");
+                    }
                 }
-            });
-            owntype = checkMethod(site,
-                    constructor,
-                    diamondResult,
-                    localEnv,
-                    tree.args,
-                    argtypes,
-                    typeargtypes,
-                    localEnv.info.varArgs).getReturnType();
-        }
-
-        return chk.checkClassType(tree.clazz.pos(), owntype, true);
-    }
+            }
 
     /** Make an attributed null check tree.
      */
@@ -1966,13 +2113,14 @@
 
     public void visitNewArray(JCNewArray tree) {
         Type owntype = types.createErrorType(tree.type);
+        Env<AttrContext> localEnv = env.dup(tree);
         Type elemtype;
         if (tree.elemtype != null) {
-            elemtype = attribType(tree.elemtype, env);
-            chk.validate(tree.elemtype, env);
+            elemtype = attribType(tree.elemtype, localEnv);
+            chk.validate(tree.elemtype, localEnv);
             owntype = elemtype;
             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
-                attribExpr(l.head, env, syms.intType);
+                attribExpr(l.head, localEnv, syms.intType);
                 owntype = new ArrayType(owntype, syms.arrayClass);
             }
         } else {
@@ -1989,7 +2137,7 @@
             }
         }
         if (tree.elems != null) {
-            attribExprs(tree.elems, env, elemtype);
+            attribExprs(tree.elems, localEnv, elemtype);
             owntype = new ArrayType(elemtype, syms.arrayClass);
         }
         if (!types.isReifiable(elemtype))
@@ -1997,14 +2145,394 @@
         result = check(tree, owntype, VAL, resultInfo);
     }
 
+    /*
+     * A lambda expression can only be attributed when a target-type is available.
+     * In addition, if the target-type is that of a functional interface whose
+     * descriptor contains inference variables in argument position the lambda expression
+     * is 'stuck' (see DeferredAttr).
+     */
     @Override
-    public void visitLambda(JCLambda that) {
-        throw new UnsupportedOperationException("Lambda expression not supported yet");
+    public void visitLambda(final JCLambda that) {
+        if (pt().isErroneous() || (pt().tag == NONE && pt() != Type.recoveryType)) {
+            if (pt().tag == NONE) {
+                //lambda only allowed in assignment or method invocation/cast context
+                log.error(that.pos(), "unexpected.lambda");
+            }
+            result = that.type = types.createErrorType(pt());
+            return;
+        }
+        //create an environment for attribution of the lambda expression
+        final Env<AttrContext> localEnv = lambdaEnv(that, env);
+        boolean needsRecovery = resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
+                resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
+        try {
+            List<Type> explicitParamTypes = null;
+            if (TreeInfo.isExplicitLambda(that)) {
+                //attribute lambda parameters
+                attribStats(that.params, localEnv);
+                explicitParamTypes = TreeInfo.types(that.params);
+            }
+
+            Type target = infer.instantiateFunctionalInterface(that, pt(), explicitParamTypes, resultInfo.checkContext);
+            Type lambdaType = (target == Type.recoveryType) ?
+                    fallbackDescriptorType(that) :
+                    types.findDescriptorType(target);
+
+            if (!TreeInfo.isExplicitLambda(that)) {
+                //add param type info in the AST
+                List<Type> actuals = lambdaType.getParameterTypes();
+                List<JCVariableDecl> params = that.params;
+
+                boolean arityMismatch = false;
+
+                while (params.nonEmpty()) {
+                    if (actuals.isEmpty()) {
+                        //not enough actuals to perform lambda parameter inference
+                        arityMismatch = true;
+                    }
+                    //reset previously set info
+                    Type argType = arityMismatch ?
+                            syms.errType :
+                            actuals.head;
+                    params.head.vartype = make.Type(argType);
+                    params.head.sym = null;
+                    actuals = actuals.isEmpty() ?
+                            actuals :
+                            actuals.tail;
+                    params = params.tail;
+                }
+
+                //attribute lambda parameters
+                attribStats(that.params, localEnv);
+
+                if (arityMismatch) {
+                    resultInfo.checkContext.report(that, diags.fragment("incompatible.arg.types.in.lambda"));
+                        result = that.type = types.createErrorType(target);
+                        return;
+                }
+            }
+
+            //from this point on, no recovery is needed; if we are in assignment context
+            //we will be able to attribute the whole lambda body, regardless of errors;
+            //if we are in a 'check' method context, and the lambda is not compatible
+            //with the target-type, it will be recovered anyway in Attr.checkId
+            needsRecovery = false;
+
+            ResultInfo bodyResultInfo = lambdaType.getReturnType() == Type.recoveryType ?
+                recoveryInfo :
+                new ResultInfo(VAL, lambdaType.getReturnType(), new LambdaReturnContext(resultInfo.checkContext));
+            localEnv.info.returnResult = bodyResultInfo;
+
+            if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
+                attribTree(that.getBody(), localEnv, bodyResultInfo);
+            } else {
+                JCBlock body = (JCBlock)that.body;
+                attribStats(body.stats, localEnv);
+            }
+
+            result = check(that, target, VAL, resultInfo);
+
+            boolean isSpeculativeRound =
+                    resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
+
+            postAttr(that);
+            flow.analyzeLambda(env, that, make, isSpeculativeRound);
+
+            checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound);
+
+            if (!isSpeculativeRound) {
+                checkAccessibleFunctionalDescriptor(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType);
+            }
+            result = check(that, target, VAL, resultInfo);
+        } catch (Types.FunctionDescriptorLookupError ex) {
+            JCDiagnostic cause = ex.getDiagnostic();
+            resultInfo.checkContext.report(that, cause);
+            result = that.type = types.createErrorType(pt());
+            return;
+        } finally {
+            localEnv.info.scope.leave();
+            if (needsRecovery) {
+                attribTree(that, env, recoveryInfo);
+            }
+        }
     }
+    //where
+        private Type fallbackDescriptorType(JCExpression tree) {
+            switch (tree.getTag()) {
+                case LAMBDA:
+                    JCLambda lambda = (JCLambda)tree;
+                    List<Type> argtypes = List.nil();
+                    for (JCVariableDecl param : lambda.params) {
+                        argtypes = param.vartype != null ?
+                                argtypes.append(param.vartype.type) :
+                                argtypes.append(syms.errType);
+                    }
+                    return new MethodType(argtypes, Type.recoveryType, List.<Type>nil(), syms.methodClass);
+                case REFERENCE:
+                    return new MethodType(List.<Type>nil(), Type.recoveryType, List.<Type>nil(), syms.methodClass);
+                default:
+                    Assert.error("Cannot get here!");
+            }
+            return null;
+        }
+
+        private void checkAccessibleFunctionalDescriptor(final DiagnosticPosition pos,
+                final Env<AttrContext> env, final InferenceContext inferenceContext, final Type desc) {
+            if (inferenceContext.free(desc)) {
+                inferenceContext.addFreeTypeListener(List.of(desc), new FreeTypeListener() {
+                    @Override
+                    public void typesInferred(InferenceContext inferenceContext) {
+                        checkAccessibleFunctionalDescriptor(pos, env, inferenceContext, inferenceContext.asInstType(desc, types));
+                    }
+                });
+            } else {
+                chk.checkAccessibleFunctionalDescriptor(pos, env, desc);
+            }
+        }
+
+        /**
+         * Lambda/method reference have a special check context that ensures
+         * that i.e. a lambda return type is compatible with the expected
+         * type according to both the inherited context and the assignment
+         * context.
+         */
+        class LambdaReturnContext extends Check.NestedCheckContext {
+            public LambdaReturnContext(CheckContext enclosingContext) {
+                super(enclosingContext);
+            }
+
+            @Override
+            public boolean compatible(Type found, Type req, Warner warn) {
+                //return type must be compatible in both current context and assignment context
+                return types.isAssignable(found, inferenceContext().asFree(req, types), warn) &&
+                        super.compatible(found, req, warn);
+            }
+            @Override
+            public void report(DiagnosticPosition pos, JCDiagnostic details) {
+                enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details));
+            }
+        }
+
+        /**
+        * Lambda compatibility. Check that given return types, thrown types, parameter types
+        * are compatible with the expected functional interface descriptor. This means that:
+        * (i) parameter types must be identical to those of the target descriptor; (ii) return
+        * types must be compatible with the return type of the expected descriptor;
+        * (iii) thrown types must be 'included' in the thrown types list of the expected
+        * descriptor.
+        */
+        private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext, boolean speculativeAttr) {
+            Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType(), types);
+
+            //return values have already been checked - but if lambda has no return
+            //values, we must ensure that void/value compatibility is correct;
+            //this amounts at checking that, if a lambda body can complete normally,
+            //the descriptor's return type must be void
+            if (tree.getBodyKind() == JCLambda.BodyKind.STATEMENT && tree.canCompleteNormally &&
+                    returnType.tag != VOID && returnType != Type.recoveryType) {
+                checkContext.report(tree, diags.fragment("incompatible.ret.type.in.lambda",
+                        diags.fragment("missing.ret.val", returnType)));
+            }
+
+            List<Type> argTypes = checkContext.inferenceContext().asFree(descriptor.getParameterTypes(), types);
+            if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) {
+                checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
+            }
+
+            if (!speculativeAttr) {
+                List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types);
+                if (chk.unhandled(tree.inferredThrownTypes == null ? List.<Type>nil() : tree.inferredThrownTypes, thrownTypes).nonEmpty()) {
+                    log.error(tree, "incompatible.thrown.types.in.lambda", tree.inferredThrownTypes);
+                }
+            }
+        }
+
+        private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
+            Env<AttrContext> lambdaEnv;
+            Symbol owner = env.info.scope.owner;
+            if (owner.kind == VAR && owner.owner.kind == TYP) {
+                //field initializer
+                lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
+                lambdaEnv.info.scope.owner =
+                    new MethodSymbol(0, names.empty, null,
+                                     env.info.scope.owner);
+            } else {
+                lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
+            }
+            return lambdaEnv;
+        }
 
     @Override
-    public void visitReference(JCMemberReference that) {
-        throw new UnsupportedOperationException("Member references not supported yet");
+    public void visitReference(final JCMemberReference that) {
+        if (pt().isErroneous() || (pt().tag == NONE && pt() != Type.recoveryType)) {
+            if (pt().tag == NONE) {
+                //method reference only allowed in assignment or method invocation/cast context
+                log.error(that.pos(), "unexpected.mref");
+            }
+            result = that.type = types.createErrorType(pt());
+            return;
+        }
+        final Env<AttrContext> localEnv = env.dup(that);
+        try {
+            //attribute member reference qualifier - if this is a constructor
+            //reference, the expected kind must be a type
+            Type exprType = attribTree(that.expr,
+                    env, new ResultInfo(that.getMode() == ReferenceMode.INVOKE ? VAL | TYP : TYP, Type.noType));
+
+            if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
+                exprType = chk.checkConstructorRefType(that.expr, exprType);
+            }
+
+            if (exprType.isErroneous()) {
+                //if the qualifier expression contains problems,
+                //give up atttribution of method reference
+                result = that.type = exprType;
+                return;
+            }
+
+            if (TreeInfo.isStaticSelector(that.expr, names) &&
+                    (that.getMode() != ReferenceMode.NEW || !that.expr.type.isRaw())) {
+                //if the qualifier is a type, validate it
+                chk.validate(that.expr, env);
+            }
+
+            //attrib type-arguments
+            List<Type> typeargtypes = null;
+            if (that.typeargs != null) {
+                typeargtypes = attribTypes(that.typeargs, localEnv);
+            }
+
+            Type target = infer.instantiateFunctionalInterface(that, pt(), null, resultInfo.checkContext);
+            Type desc = (target == Type.recoveryType) ?
+                    fallbackDescriptorType(that) :
+                    types.findDescriptorType(target);
+
+            List<Type> argtypes = desc.getParameterTypes();
+
+            boolean allowBoxing =
+                    resultInfo.checkContext.deferredAttrContext() == deferredAttr.emptyDeferredAttrContext ||
+                    resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
+            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
+                    that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
+
+            Symbol refSym = refResult.fst;
+            Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
+
+            if (refSym.kind != MTH) {
+                boolean targetError;
+                switch (refSym.kind) {
+                    case ABSENT_MTH:
+                        targetError = false;
+                        break;
+                    case WRONG_MTH:
+                    case WRONG_MTHS:
+                    case AMBIGUOUS:
+                    case HIDDEN:
+                    case STATICERR:
+                    case MISSING_ENCL:
+                        targetError = true;
+                        break;
+                    default:
+                        Assert.error("unexpected result kind " + refSym.kind);
+                        targetError = false;
+                }
+
+                JCDiagnostic detailsDiag = ((Resolve.ResolveError)refSym).getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT,
+                                that, exprType.tsym, exprType, that.name, argtypes, typeargtypes);
+
+                JCDiagnostic.DiagnosticType diagKind = targetError ?
+                        JCDiagnostic.DiagnosticType.FRAGMENT : JCDiagnostic.DiagnosticType.ERROR;
+
+                JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that,
+                        "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag);
+
+                if (targetError) {
+                    resultInfo.checkContext.report(that, diag);
+                } else {
+                    log.report(diag);
+                }
+                result = that.type = types.createErrorType(target);
+                return;
+            }
+
+            if (desc.getReturnType() == Type.recoveryType) {
+                // stop here
+                result = that.type = types.createErrorType(target);
+                return;
+            }
+
+            that.sym = refSym.baseSymbol();
+            that.kind = lookupHelper.referenceKind(that.sym);
+
+            ResultInfo checkInfo =
+                    resultInfo.dup(newMethodTemplate(
+                        desc.getReturnType().tag == VOID ? Type.noType : desc.getReturnType(),
+                        lookupHelper.argtypes,
+                        typeargtypes));
+
+            Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo);
+
+            if (!refType.isErroneous()) {
+                refType = types.createMethodTypeWithReturn(refType,
+                        adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
+            }
+
+            //go ahead with standard method reference compatibility check - note that param check
+            //is a no-op (as this has been taken care during method applicability)
+            boolean isSpeculativeRound =
+                    resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
+            checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
+            if (!isSpeculativeRound) {
+                checkAccessibleFunctionalDescriptor(that, localEnv, resultInfo.checkContext.inferenceContext(), desc);
+            }
+            result = check(that, target, VAL, resultInfo);
+        } catch (Types.FunctionDescriptorLookupError ex) {
+            JCDiagnostic cause = ex.getDiagnostic();
+            resultInfo.checkContext.report(that, cause);
+            result = that.type = types.createErrorType(pt());
+            return;
+        }
+    }
+
+    @SuppressWarnings("fallthrough")
+    void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) {
+        Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType(), types);
+
+        Type resType;
+        switch (tree.getMode()) {
+            case NEW:
+                if (!tree.expr.type.isRaw()) {
+                    resType = tree.expr.type;
+                    break;
+                }
+            default:
+                resType = refType.getReturnType();
+        }
+
+        Type incompatibleReturnType = resType;
+
+        if (returnType.tag == VOID) {
+            incompatibleReturnType = null;
+        }
+
+        if (returnType.tag != VOID && resType.tag != VOID) {
+            if (resType.isErroneous() ||
+                    new LambdaReturnContext(checkContext).compatible(resType, returnType, Warner.noWarnings)) {
+                incompatibleReturnType = null;
+            }
+        }
+
+        if (incompatibleReturnType != null) {
+            checkContext.report(tree, diags.fragment("incompatible.ret.type.in.mref",
+                    diags.fragment("inconvertible.types", resType, descriptor.getReturnType())));
+        }
+
+        if (!speculativeAttr) {
+            List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes(), types);
+            if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
+                log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
+            }
+        }
     }
 
     public void visitParens(JCParens tree) {
@@ -2138,18 +2666,34 @@
         result = check(tree, owntype, VAL, resultInfo);
     }
 
-    public void visitTypeCast(JCTypeCast tree) {
+    public void visitTypeCast(final JCTypeCast tree) {
         Type clazztype = attribType(tree.clazz, env);
         chk.validate(tree.clazz, env, false);
         //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);
-        Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
+        //should we propagate the target type?
+        final ResultInfo castInfo;
+        final boolean isPoly = TreeInfo.isPoly(tree.expr, tree);
+        if (isPoly) {
+            //expression is a poly - we need to propagate target type info
+            castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) {
+                @Override
+                public boolean compatible(Type found, Type req, Warner warn) {
+                    return types.isCastable(found, req, warn);
+                }
+            });
+        } else {
+            //standalone cast - target-type info is not propagated
+            castInfo = unknownExprInfo;
+        }
+        Type exprtype = attribTree(tree.expr, localEnv, castInfo);
+        Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
         if (exprtype.constValue() != null)
             owntype = cfolder.coerce(exprtype, owntype);
         result = check(tree, capture(owntype), VAL, resultInfo);
-        chk.checkRedundantCast(localEnv, tree);
+        if (!isPoly)
+            chk.checkRedundantCast(localEnv, tree);
     }
 
     public void visitTypeTest(JCInstanceOf tree) {
@@ -2176,15 +2720,13 @@
 
     public void visitIdent(JCIdent tree) {
         Symbol sym;
-        boolean varArgs = false;
 
         // Find symbol
         if (pt().tag == METHOD || pt().tag == FORALL) {
             // 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;
+            env.info.pendingResolutionPhase = null;
             sym = rs.resolveMethod(tree.pos(), env, tree.name, pt().getParameterTypes(), pt().getTypeArguments());
-            varArgs = env.info.varArgs;
         } else if (tree.sym != null && tree.sym.kind != VAR) {
             sym = tree.sym;
         } else {
@@ -2246,7 +2788,7 @@
             while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym))
                 env1 = env1.outer;
         }
-        result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo, varArgs);
+        result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo);
     }
 
     public void visitSelect(JCFieldAccess tree) {
@@ -2289,13 +2831,13 @@
             sitesym.name == names._super;
 
         // Determine the symbol represented by the selection.
-        env.info.varArgs = false;
+        env.info.pendingResolutionPhase = null;
         Symbol sym = selectSym(tree, sitesym, site, env, resultInfo);
         if (sym.exists() && !isType(sym) && (pkind() & (PCK | TYP)) != 0) {
             site = capture(site);
             sym = selectSym(tree, sitesym, site, env, resultInfo);
         }
-        boolean varArgs = env.info.varArgs;
+        boolean varArgs = env.info.lastResolveVarargs();
         tree.sym = sym;
 
         if (site.tag == TYPEVAR && !isType(sym) && sym.kind != ERR) {
@@ -2344,9 +2886,10 @@
             } else {
                 // Check if type-qualified fields or methods are static (JLS)
                 if ((sym.flags() & STATIC) == 0 &&
+                    !env.next.tree.hasTag(REFERENCE) &&
                     sym.name != names._super &&
                     (sym.kind == VAR || sym.kind == MTH)) {
-                    rs.access(rs.new StaticError(sym),
+                    rs.accessBase(rs.new StaticError(sym),
                               tree.pos(), site, sym.name, true);
                 }
             }
@@ -2370,7 +2913,7 @@
         }
 
         env.info.selectSuper = selectSuperPrev;
-        result = checkId(tree, site, sym, env, resultInfo, varArgs);
+        result = checkId(tree, site, sym, env, resultInfo);
     }
     //where
         /** Determine symbol referenced by a Select expression,
@@ -2389,7 +2932,7 @@
             Name name = tree.name;
             switch (site.tag) {
             case PACKAGE:
-                return rs.access(
+                return rs.accessBase(
                     rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind),
                     pos, location, site, name, true);
             case ARRAY:
@@ -2413,7 +2956,7 @@
                     // We are seeing a plain identifier as selector.
                     Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind);
                     if ((resultInfo.pkind & ERRONEOUS) == 0)
-                        sym = rs.access(sym, pos, location, site, name, true);
+                        sym = rs.accessBase(sym, pos, location, site, name, true);
                     return sym;
                 }
             case WILDCARD:
@@ -2435,7 +2978,7 @@
                     Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ?
                         rs.new AccessError(env, site, sym) :
                                 sym;
-                    rs.access(sym2, pos, location, site, name, true);
+                    rs.accessBase(sym2, pos, location, site, name, true);
                     return sym;
                 }
             case ERROR:
@@ -2486,9 +3029,18 @@
                      Type site,
                      Symbol sym,
                      Env<AttrContext> env,
-                     ResultInfo resultInfo,
-                     boolean useVarargs) {
-            if (resultInfo.pt.isErroneous()) return types.createErrorType(site);
+                     ResultInfo resultInfo) {
+            Type pt = resultInfo.pt.tag == FORALL || resultInfo.pt.tag == METHOD ?
+                    resultInfo.pt.map(deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)) :
+                    resultInfo.pt;
+
+            DeferredAttr.DeferredTypeMap recoveryMap =
+                    deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
+
+            if (pt.isErroneous()) {
+                Type.map(resultInfo.pt.getParameterTypes(), recoveryMap);
+                return types.createErrorType(site);
+            }
             Type owntype; // The computed type of this identifier occurrence.
             switch (sym.kind) {
             case TYP:
@@ -2563,14 +3115,14 @@
                 }
                 break;
             case MTH: {
-                JCMethodInvocation app = (JCMethodInvocation)env.tree;
                 owntype = checkMethod(site, sym,
                         new ResultInfo(VAL, resultInfo.pt.getReturnType(), resultInfo.checkContext),
-                        env, app.args, resultInfo.pt.getParameterTypes(),
-                        resultInfo.pt.getTypeArguments(), env.info.varArgs);
+                        env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(),
+                        resultInfo.pt.getTypeArguments());
                 break;
             }
             case PCK: case ERR:
+                Type.map(resultInfo.pt.getParameterTypes(), recoveryMap);
                 owntype = sym.type;
                 break;
             default:
@@ -2710,8 +3262,7 @@
                             Env<AttrContext> env,
                             final List<JCExpression> argtrees,
                             List<Type> argtypes,
-                            List<Type> typeargtypes,
-                            boolean useVarargs) {
+                            List<Type> typeargtypes) {
         // Test (5): if symbol is an instance method of a raw type, issue
         // an unchecked warning if its argument types change under erasure.
         if (allowGenerics &&
@@ -2733,18 +3284,16 @@
         // any type arguments and value arguments.
         noteWarner.clear();
         try {
-            Type owntype = rs.rawInstantiate(
+            Type owntype = rs.checkMethod(
                     env,
                     site,
                     sym,
                     resultInfo,
                     argtypes,
                     typeargtypes,
-                    allowBoxing,
-                    useVarargs,
                     noteWarner);
 
-            return chk.checkMethod(owntype, sym, env, argtrees, argtypes, useVarargs,
+            return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(),
                     noteWarner.hasNonSilentLint(LintCategory.UNCHECKED));
         } catch (Infer.InferenceException ex) {
             //invalid target type - propagate exception outwards or report error
@@ -2752,26 +3301,11 @@
             resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic());
             return types.createErrorType(site);
         } catch (Resolve.InapplicableMethodException ex) {
-            Assert.error();
+            Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault()));
             return null;
         }
     }
 
-    /**
-     * Check that constructor arguments conform to its instantiation.
-     **/
-    public Type checkConstructor(Type site,
-                            Symbol sym,
-                            Env<AttrContext> env,
-                            final List<JCExpression> argtrees,
-                            List<Type> argtypes,
-                            List<Type> typeargtypes,
-                            boolean useVarargs) {
-        Type owntype = checkMethod(site, sym, new ResultInfo(VAL, syms.voidType), env, argtrees, argtypes, typeargtypes, useVarargs);
-        chk.checkType(env.tree.pos(), owntype.getReturnType(), syms.voidType);
-        return owntype;
-    }
-
     public void visitLiteral(JCLiteral tree) {
         result = check(
             tree, litType(tree.typetag).constType(tree.value), VAL, resultInfo);
@@ -3075,8 +3609,10 @@
 
             Lint prevLint = chk.setLint(env.info.lint);
             JavaFileObject prev = log.useSource(c.sourcefile);
+            ResultInfo prevReturnRes = env.info.returnResult;
 
             try {
+                env.info.returnResult = null;
                 // java.lang.Enum may not be subclassed by a non-enum
                 if (st.tsym == syms.enumSym &&
                     ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0))
@@ -3093,6 +3629,7 @@
 
                 chk.checkDeprecatedAnnotation(env.tree.pos(), c);
             } finally {
+                env.info.returnResult = prevReturnRes;
                 log.useSource(prev);
                 chk.setLint(prevLint);
             }
@@ -3280,8 +3817,8 @@
      * mode (e.g. by an IDE) and the AST contains semantic errors, this routine
      * prevents NPE to be progagated during subsequent compilation steps.
      */
-    public void postAttr(Env<AttrContext> env) {
-        new PostAttrAnalyzer().scan(env.tree);
+    public void postAttr(JCTree tree) {
+        new PostAttrAnalyzer().scan(tree);
     }
 
     class PostAttrAnalyzer extends TreeScanner {
@@ -3375,6 +3912,14 @@
                 that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol);
             super.visitUnary(that);
         }
+
+        @Override
+        public void visitReference(JCMemberReference that) {
+            super.visitReference(that);
+            if (that.sym == null) {
+                that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol);
+            }
+        }
     }
     // </editor-fold>
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java	Thu Oct 11 17:00:54 2012 -0700
@@ -56,7 +56,7 @@
 
     /** Are arguments to current function applications boxed into an array for varargs?
      */
-    boolean varArgs = false;
+    Resolve.MethodResolutionPhase pendingResolutionPhase = null;
 
     /** A record of the lint/SuppressWarnings currently in effect
      */
@@ -67,6 +67,11 @@
      */
     Symbol enclVar = null;
 
+    /** ResultInfo to be used for attributing 'return' statement expressions
+     * (set by Attr.visitMethod and Attr.visitLambda)
+     */
+    Attr.ResultInfo returnResult = null;
+
     /** Duplicate this context, replacing scope field and copying all others.
      */
     AttrContext dup(Scope scope) {
@@ -75,9 +80,10 @@
         info.staticLevel = staticLevel;
         info.isSelfCall = isSelfCall;
         info.selectSuper = selectSuper;
-        info.varArgs = varArgs;
+        info.pendingResolutionPhase = pendingResolutionPhase;
         info.lint = lint;
         info.enclVar = enclVar;
+        info.returnResult = returnResult;
         return info;
     }
 
@@ -93,6 +99,11 @@
         return scope.getElements();
     }
 
+    boolean lastResolveVarargs() {
+        return pendingResolutionPhase != null &&
+                pendingResolutionPhase.isVarargsRequired();
+    }
+
     public String toString() {
         return "AttrContext[" + scope.toString() + "]";
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Oct 11 17:00:54 2012 -0700
@@ -40,6 +40,9 @@
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
@@ -66,6 +69,7 @@
     private final Resolve rs;
     private final Symtab syms;
     private final Enter enter;
+    private final DeferredAttr deferredAttr;
     private final Infer infer;
     private final Types types;
     private final JCDiagnostic.Factory diags;
@@ -98,6 +102,7 @@
         rs = Resolve.instance(context);
         syms = Symtab.instance(context);
         enter = Enter.instance(context);
+        deferredAttr = DeferredAttr.instance(context);
         infer = Infer.instance(context);
         this.types = Types.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
@@ -416,7 +421,7 @@
      * checks - depending on the check context, meaning of 'compatibility' might
      * vary significantly.
      */
-    interface CheckContext {
+    public interface CheckContext {
         /**
          * Is type 'found' compatible with type 'req' in given context
          */
@@ -429,6 +434,12 @@
          * Obtain a warner for this check context
          */
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
+
+        public Infer.InferenceContext inferenceContext();
+
+        public DeferredAttr.DeferredAttrContext deferredAttrContext();
+
+        public boolean allowBoxing();
     }
 
     /**
@@ -455,6 +466,18 @@
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
             return enclosingContext.checkWarner(pos, found, req);
         }
+
+        public Infer.InferenceContext inferenceContext() {
+            return enclosingContext.inferenceContext();
+        }
+
+        public DeferredAttrContext deferredAttrContext() {
+            return enclosingContext.deferredAttrContext();
+        }
+
+        public boolean allowBoxing() {
+            return enclosingContext.allowBoxing();
+        }
     }
 
     /**
@@ -471,6 +494,18 @@
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
             return convertWarner(pos, found, req);
         }
+
+        public InferenceContext inferenceContext() {
+            return infer.emptyContext;
+        }
+
+        public DeferredAttrContext deferredAttrContext() {
+            return deferredAttr.emptyDeferredAttrContext;
+        }
+
+        public boolean allowBoxing() {
+            return true;
+        }
     };
 
     /** Check that a given type is assignable to a given proto-type.
@@ -483,7 +518,16 @@
         return checkType(pos, found, req, basicHandler);
     }
 
-    Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
+    Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
+        final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
+        if (inferenceContext.free(req)) {
+            inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
+                @Override
+                public void typesInferred(InferenceContext inferenceContext) {
+                    checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
+                }
+            });
+        }
         if (req.tag == ERROR)
             return req;
         if (req.tag == NONE)
@@ -523,9 +567,9 @@
      */
     public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
         if (!tree.type.isErroneous() &&
-            (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
-            && types.isSameType(tree.expr.type, tree.clazz.type)
-            && !is292targetTypeCast(tree)) {
+                (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
+                && types.isSameType(tree.expr.type, tree.clazz.type)
+                && !is292targetTypeCast(tree)) {
             log.warning(Lint.LintCategory.CAST,
                     tree.pos(), "redundant.cast", tree.expr.type);
         }
@@ -604,6 +648,22 @@
             return t;
     }
 
+    /** Check that type is a valid qualifier for a constructor reference expression
+     */
+    Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
+        t = checkClassType(pos, t);
+        if (t.tag == CLASS) {
+            if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
+                log.error(pos, "abstract.cant.be.instantiated");
+                t = types.createErrorType(t);
+            } else if ((t.tsym.flags() & ENUM) != 0) {
+                log.error(pos, "enum.cant.be.instantiated");
+                t = types.createErrorType(t);
+            }
+        }
+        return t;
+    }
+
     /** Check that type is a class or interface type.
      *  @param pos           Position to be used for error reporting.
      *  @param t             The type to be checked.
@@ -796,29 +856,34 @@
                 sym.owner == syms.enumSym)
                 formals = formals.tail.tail;
         List<JCExpression> args = argtrees;
-        while (formals.head != last) {
-            JCTree arg = args.head;
-            Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
-            assertConvertible(arg, arg.type, formals.head, warn);
-            args = args.tail;
-            formals = formals.tail;
-        }
-        if (useVarargs) {
-            Type varArg = types.elemtype(last);
-            while (args.tail != null) {
+        DeferredAttr.DeferredTypeMap checkDeferredMap =
+                deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
+        if (args != null) {
+            //this is null when type-checking a method reference
+            while (formals.head != last) {
                 JCTree arg = args.head;
-                Warner warn = convertWarner(arg.pos(), arg.type, varArg);
-                assertConvertible(arg, arg.type, varArg, warn);
+                Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
+                assertConvertible(arg, arg.type, formals.head, warn);
                 args = args.tail;
+                formals = formals.tail;
             }
-        } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
-            // non-varargs call to varargs method
-            Type varParam = owntype.getParameterTypes().last();
-            Type lastArg = argtypes.last();
-            if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
-                    !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
-                log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
-                        types.elemtype(varParam), varParam);
+            if (useVarargs) {
+                Type varArg = types.elemtype(last);
+                while (args.tail != null) {
+                    JCTree arg = args.head;
+                    Warner warn = convertWarner(arg.pos(), arg.type, varArg);
+                    assertConvertible(arg, arg.type, varArg, warn);
+                    args = args.tail;
+                }
+            } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
+                // non-varargs call to varargs method
+                Type varParam = owntype.getParameterTypes().last();
+                Type lastArg = checkDeferredMap.apply(argtypes.last());
+                if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
+                        !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
+                    log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
+                            types.elemtype(varParam), varParam);
+            }
         }
         if (unchecked) {
             warnUnchecked(env.tree.pos(),
@@ -826,7 +891,7 @@
                     kindName(sym),
                     sym.name,
                     rs.methodArguments(sym.type.getParameterTypes()),
-                    rs.methodArguments(argtypes),
+                    rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
                     kindName(sym.location()),
                     sym.location());
            owntype = new MethodType(owntype.getParameterTypes(),
@@ -853,6 +918,9 @@
                 case NEWCLASS:
                     ((JCNewClass) tree).varargsElement = elemtype;
                     break;
+                case REFERENCE:
+                    ((JCMemberReference) tree).varargsElement = elemtype;
+                    break;
                 default:
                     throw new AssertionError(""+tree);
             }
@@ -870,6 +938,65 @@
                 return;
         }
 
+        void checkAccessibleFunctionalDescriptor(DiagnosticPosition pos, Env<AttrContext> env, Type desc) {
+            AccessChecker accessChecker = new AccessChecker(env);
+            //check args accessibility (only if implicit parameter types)
+            for (Type arg : desc.getParameterTypes()) {
+                if (!accessChecker.visit(arg)) {
+                    log.error(pos, "cant.access.arg.type.in.functional.desc", arg);
+                    return;
+                }
+            }
+            //check return type accessibility
+            if (!accessChecker.visit(desc.getReturnType())) {
+                log.error(pos, "cant.access.return.in.functional.desc", desc.getReturnType());
+                return;
+            }
+            //check thrown types accessibility
+            for (Type thrown : desc.getThrownTypes()) {
+                if (!accessChecker.visit(thrown)) {
+                    log.error(pos, "cant.access.thrown.in.functional.desc", thrown);
+                    return;
+                }
+            }
+        }
+
+        class AccessChecker extends Types.UnaryVisitor<Boolean> {
+
+            Env<AttrContext> env;
+
+            AccessChecker(Env<AttrContext> env) {
+                this.env = env;
+            }
+
+            Boolean visit(List<Type> ts) {
+                for (Type t : ts) {
+                    if (!visit(t))
+                        return false;
+                }
+                return true;
+            }
+
+            public Boolean visitType(Type t, Void s) {
+                return true;
+            }
+
+            @Override
+            public Boolean visitArrayType(ArrayType t, Void s) {
+                return visit(t.elemtype);
+            }
+
+            @Override
+            public Boolean visitClassType(ClassType t, Void s) {
+                return rs.isAccessible(env, t, true) &&
+                        visit(t.getTypeArguments());
+            }
+
+            @Override
+            public Boolean visitWildcardType(WildcardType t, Void s) {
+                return visit(t.type);
+            }
+        };
     /**
      * Check that type 't' is a valid instantiation of a generic class
      * (see JLS 4.5)
@@ -2470,6 +2597,7 @@
         validateDocumented(t.tsym, s, pos);
         validateInherited(t.tsym, s, pos);
         validateTarget(t.tsym, s, pos);
+        validateDefault(t.tsym, s, pos);
     }
 
     /**
@@ -2650,6 +2778,21 @@
         return true;
     }
 
+    private void validateDefault(Symbol container, Symbol contained, DiagnosticPosition pos) {
+        // validate that all other elements of containing type has defaults
+        Scope scope = container.members();
+        for(Symbol elm : scope.getElements()) {
+            if (elm.name != names.value &&
+                elm.kind == Kinds.MTH &&
+                ((MethodSymbol)elm).defaultValue == null) {
+                log.error(pos,
+                          "invalid.containedby.annotation.elem.nondefault",
+                          container,
+                          elm);
+            }
+        }
+    }
+
     /** Is s a method symbol that overrides a method in a superclass? */
     boolean isOverrider(Symbol s) {
         if (s.kind != MTH || s.isStatic())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.comp;
+
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.comp.Attr.ResultInfo;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
+import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
+import com.sun.tools.javac.tree.JCTree.*;
+
+import javax.tools.JavaFileObject;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import static com.sun.tools.javac.code.TypeTags.*;
+import static com.sun.tools.javac.tree.JCTree.Tag.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+
+/**
+ * This is an helper class that is used to perform deferred type-analysis.
+ * Each time a poly expression occurs in argument position, javac attributes it
+ * with a temporary 'deferred type' that is checked (possibly multiple times)
+ * against an expected formal type.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class DeferredAttr extends JCTree.Visitor {
+    protected static final Context.Key<DeferredAttr> deferredAttrKey =
+        new Context.Key<DeferredAttr>();
+
+    final Attr attr;
+    final Check chk;
+    final Enter enter;
+    final Infer infer;
+    final Log log;
+    final Symtab syms;
+    final TreeMaker make;
+    final Types types;
+
+    public static DeferredAttr instance(Context context) {
+        DeferredAttr instance = context.get(deferredAttrKey);
+        if (instance == null)
+            instance = new DeferredAttr(context);
+        return instance;
+    }
+
+    protected DeferredAttr(Context context) {
+        context.put(deferredAttrKey, this);
+        attr = Attr.instance(context);
+        chk = Check.instance(context);
+        enter = Enter.instance(context);
+        infer = Infer.instance(context);
+        log = Log.instance(context);
+        syms = Symtab.instance(context);
+        make = TreeMaker.instance(context);
+        types = Types.instance(context);
+    }
+
+    /**
+     * This type represents a deferred type. A deferred type starts off with
+     * no information on the underlying expression type. Such info needs to be
+     * discovered through type-checking the deferred type against a target-type.
+     * Every deferred type keeps a pointer to the AST node from which it originated.
+     */
+    public class DeferredType extends Type {
+
+        public JCExpression tree;
+        Env<AttrContext> env;
+        AttrMode mode;
+        SpeculativeCache speculativeCache;
+
+        DeferredType(JCExpression tree, Env<AttrContext> env) {
+            super(DEFERRED, null);
+            this.tree = tree;
+            this.env = env.dup(tree, env.info.dup());
+            this.speculativeCache = new SpeculativeCache();
+        }
+
+        /**
+         * A speculative cache is used to keep track of all overload resolution rounds
+         * that triggered speculative attribution on a given deferred type. Each entry
+         * stores a pointer to the speculative tree and the resolution phase in which the entry
+         * has been added.
+         */
+        class SpeculativeCache {
+
+            private Map<Symbol, List<Entry>> cache =
+                    new WeakHashMap<Symbol, List<Entry>>();
+
+            class Entry {
+                JCTree speculativeTree;
+                Resolve.MethodResolutionPhase phase;
+
+                public Entry(JCTree speculativeTree, MethodResolutionPhase phase) {
+                    this.speculativeTree = speculativeTree;
+                    this.phase = phase;
+                }
+
+                boolean matches(Resolve.MethodResolutionPhase phase) {
+                    return this.phase == phase;
+                }
+            }
+
+            /**
+             * Clone a speculative cache entry as a fresh entry associated
+             * with a new method (this maybe required to fixup speculative cache
+             * misses after Resolve.access())
+             */
+            void dupAllTo(Symbol from, Symbol to) {
+                Assert.check(cache.get(to) == null);
+                List<Entry> entries = cache.get(from);
+                if (entries != null) {
+                    cache.put(to, entries);
+                }
+            }
+
+            /**
+             * Retrieve a speculative cache entry corresponding to given symbol
+             * and resolution phase
+             */
+            Entry get(Symbol msym, MethodResolutionPhase phase) {
+                List<Entry> entries = cache.get(msym);
+                if (entries == null) return null;
+                for (Entry e : entries) {
+                    if (e.matches(phase)) return e;
+                }
+                return null;
+            }
+
+            /**
+             * Stores a speculative cache entry corresponding to given symbol
+             * and resolution phase
+             */
+            void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) {
+                List<Entry> entries = cache.get(msym);
+                if (entries == null) {
+                    entries = List.nil();
+                }
+                cache.put(msym, entries.prepend(new Entry(speculativeTree, phase)));
+            }
+        }
+
+        /**
+         * Get the type that has been computed during a speculative attribution round
+         */
+        Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
+            SpeculativeCache.Entry e = speculativeCache.get(msym, phase);
+            return e != null ? e.speculativeTree.type : Type.noType;
+        }
+
+        /**
+         * Check a deferred type against a potential target-type. Depending on
+         * the current attribution mode, a normal vs. speculative attribution
+         * round is performed on the underlying AST node. There can be only one
+         * speculative round for a given target method symbol; moreover, a normal
+         * attribution round must follow one or more speculative rounds.
+         */
+        Type check(ResultInfo resultInfo) {
+            DeferredAttrContext deferredAttrContext =
+                    resultInfo.checkContext.deferredAttrContext();
+            Assert.check(deferredAttrContext != emptyDeferredAttrContext);
+            List<Type> stuckVars = stuckVars(tree, resultInfo);
+            if (stuckVars.nonEmpty()) {
+                deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
+                return Type.noType;
+            } else {
+                try {
+                    switch (deferredAttrContext.mode) {
+                        case SPECULATIVE:
+                            Assert.check(mode == null ||
+                                    (mode == AttrMode.SPECULATIVE &&
+                                    speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).tag == NONE));
+                            JCTree speculativeTree = attribSpeculative(tree, env, resultInfo);
+                            speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
+                            return speculativeTree.type;
+                        case CHECK:
+                            Assert.check(mode == AttrMode.SPECULATIVE);
+                            return attr.attribTree(tree, env, resultInfo);
+                    }
+                    Assert.error();
+                    return null;
+                } finally {
+                    mode = deferredAttrContext.mode;
+                }
+            }
+        }
+    }
+
+    /**
+     * The 'mode' in which the deferred type is to be type-checked
+     */
+    public enum AttrMode {
+        /**
+         * A speculative type-checking round is used during overload resolution
+         * mainly to generate constraints on inference variables. Side-effects
+         * arising from type-checking the expression associated with the deferred
+         * type are reversed after the speculative round finishes. This means the
+         * expression tree will be left in a blank state.
+         */
+        SPECULATIVE,
+        /**
+         * This is the plain type-checking mode. Produces side-effects on the underlying AST node
+         */
+        CHECK;
+    }
+
+    /**
+     * Routine that performs speculative type-checking; the input AST node is
+     * cloned (to avoid side-effects cause by Attr) and compiler state is
+     * restored after type-checking. All diagnostics (but critical ones) are
+     * disabled during speculative type-checking.
+     */
+    JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
+        JCTree newTree = new TreeCopier<Object>(make).copy(tree);
+        Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
+        speculativeEnv.info.scope.owner = env.info.scope.owner;
+        Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
+        Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
+        final JavaFileObject currentSource = log.currentSourceFile();
+        try {
+            log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
+            log.deferredDiagFilter = new Filter<JCDiagnostic>() {
+                public boolean accepts(JCDiagnostic t) {
+                    return t.getDiagnosticSource().getFile().equals(currentSource);
+                }
+            };
+            attr.attribTree(newTree, speculativeEnv, resultInfo);
+            unenterScanner.scan(newTree);
+            return newTree;
+        } catch (Abort ex) {
+            //if some very bad condition occurred during deferred attribution
+            //we should dump all errors before killing javac
+            log.reportDeferredDiagnostics();
+            throw ex;
+        } finally {
+            unenterScanner.scan(newTree);
+            log.deferredDiagFilter = prevDeferDiagsFilter;
+            log.deferredDiagnostics = prevDeferredDiags;
+        }
+    }
+    //where
+        protected TreeScanner unenterScanner = new TreeScanner() {
+            @Override
+            public void visitClassDef(JCClassDecl tree) {
+                ClassSymbol csym = tree.sym;
+                enter.typeEnvs.remove(csym);
+                chk.compiled.remove(csym.flatname);
+                syms.classes.remove(csym.flatname);
+                super.visitClassDef(tree);
+            }
+        };
+
+    /**
+     * A deferred context is created on each method check. A deferred context is
+     * used to keep track of information associated with the method check, such as
+     * the symbol of the method being checked, the overload resolution phase,
+     * the kind of attribution mode to be applied to deferred types and so forth.
+     * As deferred types are processed (by the method check routine) stuck AST nodes
+     * are added (as new deferred attribution nodes) to this context. The complete()
+     * routine makes sure that all pending nodes are properly processed, by
+     * progressively instantiating all inference variables on which one or more
+     * deferred attribution node is stuck.
+     */
+    class DeferredAttrContext {
+
+        /** attribution mode */
+        final AttrMode mode;
+
+        /** symbol of the method being checked */
+        final Symbol msym;
+
+        /** method resolution step */
+        final Resolve.MethodResolutionPhase phase;
+
+        /** inference context */
+        final InferenceContext inferenceContext;
+
+        /** list of deferred attribution nodes to be processed */
+        ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
+
+        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) {
+            this.mode = mode;
+            this.msym = msym;
+            this.phase = phase;
+            this.inferenceContext = inferenceContext;
+        }
+
+        /**
+         * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
+         * Nodes added this way act as 'roots' for the out-of-order method checking process.
+         */
+        void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
+            deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars));
+        }
+
+        /**
+         * Incrementally process all nodes, by skipping 'stuck' nodes and attributing
+         * 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes)
+         * some inference variable might get eagerly instantiated so that all nodes
+         * can be type-checked.
+         */
+        void complete() {
+            while (!deferredAttrNodes.isEmpty()) {
+                Set<Type> stuckVars = new HashSet<Type>();
+                boolean progress = false;
+                //scan a defensive copy of the node list - this is because a deferred
+                //attribution round can add new nodes to the list
+                for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
+                    if (!deferredAttrNode.isStuck()) {
+                        deferredAttrNode.process();
+                        deferredAttrNodes.remove(deferredAttrNode);
+                        progress = true;
+                    } else {
+                        stuckVars.addAll(deferredAttrNode.stuckVars);
+                    }
+                }
+                if (!progress) {
+                    //remove all variables that have already been instantiated
+                    //from the list of stuck variables
+                    inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer);
+                    inferenceContext.notifyChange(types);
+                }
+            }
+        }
+
+        /**
+         * Class representing a deferred attribution node. It keeps track of
+         * a deferred type, along with the expected target type information.
+         */
+        class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener {
+
+            /** underlying deferred type */
+            DeferredType dt;
+
+            /** underlying target type information */
+            ResultInfo resultInfo;
+
+            /** list of uninferred inference variables causing this node to be stuck */
+            List<Type> stuckVars;
+
+            DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
+                this.dt = dt;
+                this.resultInfo = resultInfo;
+                this.stuckVars = stuckVars;
+                if (!stuckVars.isEmpty()) {
+                    resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+                }
+            }
+
+            @Override
+            public void typesInferred(InferenceContext inferenceContext) {
+                stuckVars = List.nil();
+                resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
+            }
+
+            /**
+             * is this node stuck?
+             */
+            boolean isStuck() {
+                return stuckVars.nonEmpty();
+            }
+
+            /**
+             * Process a deferred attribution node.
+             * Invariant: a stuck node cannot be processed.
+             */
+            void process() {
+                if (isStuck()) {
+                    throw new IllegalStateException("Cannot process a stuck deferred node");
+                }
+                dt.check(resultInfo);
+            }
+        }
+    }
+
+    /** an empty deferred attribution context - all methods throw exceptions */
+    final DeferredAttrContext emptyDeferredAttrContext =
+            new DeferredAttrContext(null, null, null, null) {
+                @Override
+                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
+                    Assert.error("Empty deferred context!");
+                }
+                @Override
+                void complete() {
+                    Assert.error("Empty deferred context!");
+                }
+            };
+
+    /**
+     * Map a list of types possibly containing one or more deferred types
+     * into a list of ordinary types. Each deferred type D is mapped into a type T,
+     * where T is computed by retrieving the type that has already been
+     * computed for D during a previous deferred attribution round of the given kind.
+     */
+    class DeferredTypeMap extends Type.Mapping {
+
+        DeferredAttrContext deferredAttrContext;
+
+        protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
+            super(String.format("deferredTypeMap[%s]", mode));
+            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext);
+        }
+
+        protected boolean validState(DeferredType dt) {
+            return dt.mode != null &&
+                    deferredAttrContext.mode.ordinal() <= dt.mode.ordinal();
+        }
+
+        @Override
+        public Type apply(Type t) {
+            if (t.tag != DEFERRED) {
+                return t.map(this);
+            } else {
+                DeferredType dt = (DeferredType)t;
+                Assert.check(validState(dt));
+                return typeOf(dt);
+            }
+        }
+
+        protected Type typeOf(DeferredType dt) {
+            switch (deferredAttrContext.mode) {
+                case CHECK:
+                    return dt.tree.type == null ? Type.noType : dt.tree.type;
+                case SPECULATIVE:
+                    return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase);
+            }
+            Assert.error();
+            return null;
+        }
+    }
+
+    /**
+     * Specialized recovery deferred mapping.
+     * Each deferred type D is mapped into a type T, where T is computed either by
+     * (i) retrieving the type that has already been computed for D during a previous
+     * attribution round (as before), or (ii) by synthesizing a new type R for D
+     * (the latter step is useful in a recovery scenario).
+     */
+    public class RecoveryDeferredTypeMap extends DeferredTypeMap {
+
+        public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
+            super(mode, msym, phase);
+        }
+
+        @Override
+        protected Type typeOf(DeferredType dt) {
+            Type owntype = super.typeOf(dt);
+            return owntype.tag == NONE ?
+                        recover(dt) : owntype;
+        }
+
+        @Override
+        protected boolean validState(DeferredType dt) {
+            return true;
+        }
+
+        /**
+         * Synthesize a type for a deferred type that hasn't been previously
+         * reduced to an ordinary type. Functional deferred types and conditionals
+         * are mapped to themselves, in order to have a richer diagnostic
+         * representation. Remaining deferred types are attributed using
+         * a default expected type (j.l.Object).
+         */
+        private Type recover(DeferredType dt) {
+            dt.check(attr.new RecoveryInfo(deferredAttrContext));
+            switch (TreeInfo.skipParens(dt.tree).getTag()) {
+                case LAMBDA:
+                case REFERENCE:
+                case CONDEXPR:
+                    //propagate those deferred types to the
+                    //diagnostic formatter
+                    return dt;
+                default:
+                    return super.apply(dt);
+            }
+        }
+    }
+
+    /**
+     * Retrieves the list of inference variables that need to be inferred before
+     * an AST node can be type-checked
+     */
+    @SuppressWarnings("fallthrough")
+    List<Type> stuckVars(JCTree tree, ResultInfo resultInfo) {
+        if (resultInfo.pt.tag == NONE || resultInfo.pt.isErroneous()) {
+            return List.nil();
+        } else {
+            StuckChecker sc = new StuckChecker(resultInfo);
+            sc.scan(tree);
+            return List.from(sc.stuckVars);
+        }
+    }
+
+    /**
+     * This visitor is used to check that structural expressions conform
+     * to their target - this step is required as inference could end up
+     * inferring types that make some of the nested expressions incompatible
+     * with their corresponding instantiated target
+     */
+    class StuckChecker extends TreeScanner {
+
+        Type pt;
+        Filter<JCTree> treeFilter;
+        Infer.InferenceContext inferenceContext;
+        Set<Type> stuckVars = new HashSet<Type>();
+
+        final Filter<JCTree> argsFilter = new Filter<JCTree>() {
+            public boolean accepts(JCTree t) {
+                switch (t.getTag()) {
+                    case CONDEXPR:
+                    case LAMBDA:
+                    case PARENS:
+                    case REFERENCE:
+                        return true;
+                    default:
+                        return false;
+                }
+            }
+        };
+
+        final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
+            public boolean accepts(JCTree t) {
+                switch (t.getTag()) {
+                    case BLOCK: case CASE: case CATCH: case DOLOOP:
+                    case FOREACHLOOP: case FORLOOP: case RETURN:
+                    case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
+                        return true;
+                    default:
+                        return false;
+                }
+            }
+        };
+
+        StuckChecker(ResultInfo resultInfo) {
+            this.pt = resultInfo.pt;
+            this.inferenceContext = resultInfo.checkContext.inferenceContext();
+            this.treeFilter = argsFilter;
+        }
+
+        @Override
+        public void scan(JCTree tree) {
+            if (tree != null && treeFilter.accepts(tree)) {
+                super.scan(tree);
+            }
+        }
+
+        @Override
+        public void visitLambda(JCLambda tree) {
+            Type prevPt = pt;
+            Filter<JCTree> prevFilter = treeFilter;
+            try {
+                if (inferenceContext.inferenceVars().contains(pt)) {
+                    stuckVars.add(pt);
+                }
+                if (!types.isFunctionalInterface(pt.tsym)) {
+                    return;
+                }
+                Type descType = types.findDescriptorType(pt);
+                List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
+                if (!TreeInfo.isExplicitLambda(tree) &&
+                        freeArgVars.nonEmpty()) {
+                    stuckVars.addAll(freeArgVars);
+                }
+                pt = descType.getReturnType();
+                if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
+                    scan(tree.getBody());
+                } else {
+                    treeFilter = lambdaBodyFilter;
+                    super.visitLambda(tree);
+                }
+            } finally {
+                pt = prevPt;
+                treeFilter = prevFilter;
+            }
+        }
+
+        @Override
+        public void visitReference(JCMemberReference tree) {
+            scan(tree.expr);
+            if (inferenceContext.inferenceVars().contains(pt)) {
+                stuckVars.add(pt);
+                return;
+            }
+            if (!types.isFunctionalInterface(pt.tsym)) {
+                return;
+            }
+            Type descType = types.findDescriptorType(pt);
+            List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
+            stuckVars.addAll(freeArgVars);
+        }
+
+        @Override
+        public void visitReturn(JCReturn tree) {
+            Filter<JCTree> prevFilter = treeFilter;
+            try {
+                treeFilter = argsFilter;
+                if (tree.expr != null) {
+                    scan(tree.expr);
+                }
+            } finally {
+                treeFilter = prevFilter;
+            }
+        }
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Oct 11 17:00:54 2012 -0700
@@ -50,8 +50,8 @@
  *  (see AssignAnalyzer) ensures that each variable is assigned when used.  Definite
  *  unassignment analysis (see AssignAnalyzer) in ensures that no final variable
  *  is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
- *  determines that local variables accessed within the scope of an inner class are
- *  either final or effectively-final.
+ *  determines that local variables accessed within the scope of an inner class/lambda
+ *  are either final or effectively-final.
  *
  *  <p>The JLS has a number of problems in the
  *  specification of these flow analysis problems. This implementation
@@ -211,6 +211,29 @@
         new CaptureAnalyzer().analyzeTree(env, make);
     }
 
+    public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
+        java.util.Queue<JCDiagnostic> prevDeferredDiagnostics = log.deferredDiagnostics;
+        Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
+        //we need to disable diagnostics temporarily; the problem is that if
+        //a lambda expression contains e.g. an unreachable statement, an error
+        //message will be reported and will cause compilation to skip the flow analyis
+        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
+        //related errors, which will allow for more errors to be detected
+        if (!speculative) {
+            log.deferAll();
+            log.deferredDiagnostics = ListBuffer.lb();
+        }
+        try {
+            new AliveAnalyzer().analyzeTree(env, that, make);
+            new FlowAnalyzer().analyzeTree(env, that, make);
+        } finally {
+            if (!speculative) {
+                log.deferredDiagFilter = prevDeferDiagsFilter;
+                log.deferredDiagnostics = prevDeferredDiagnostics;
+            }
+        }
+    }
+
     /**
      * Definite assignment scan mode
      */
@@ -659,6 +682,27 @@
             }
         }
 
+        @Override
+        public void visitLambda(JCLambda tree) {
+            if (tree.type != null &&
+                    tree.type.isErroneous()) {
+                return;
+            }
+
+            ListBuffer<PendingExit> prevPending = pendingExits;
+            boolean prevAlive = alive;
+            try {
+                pendingExits = ListBuffer.lb();
+                alive = true;
+                scanStat(tree.body);
+                tree.canCompleteNormally = alive;
+            }
+            finally {
+                pendingExits = prevPending;
+                alive = prevAlive;
+            }
+        }
+
         public void visitTopLevel(JCCompilationUnit tree) {
             // Do nothing for TopLevel since each class is visited individually
         }
@@ -670,6 +714,9 @@
         /** Perform definite assignment/unassignment analysis on a tree.
          */
         public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
+            analyzeTree(env, env.tree, make);
+        }
+        public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
             try {
                 attrEnv = env;
                 Flow.this.make = make;
@@ -1185,6 +1232,29 @@
             }
         }
 
+        @Override
+        public void visitLambda(JCLambda tree) {
+            if (tree.type != null &&
+                    tree.type.isErroneous()) {
+                return;
+            }
+            List<Type> prevCaught = caught;
+            List<Type> prevThrown = thrown;
+            ListBuffer<FlowPendingExit> prevPending = pendingExits;
+            try {
+                pendingExits = ListBuffer.lb();
+                caught = List.of(syms.throwableType); //inhibit exception checking
+                thrown = List.nil();
+                scan(tree.body);
+                tree.inferredThrownTypes = thrown;
+            }
+            finally {
+                pendingExits = prevPending;
+                caught = prevCaught;
+                thrown = prevThrown;
+            }
+        }
+
         public void visitTopLevel(JCCompilationUnit tree) {
             // Do nothing for TopLevel since each class is visited individually
         }
@@ -1267,6 +1337,10 @@
          */
         int nextadr;
 
+        /** The first variable sequence number in a block that can return.
+         */
+        int returnadr;
+
         /** The list of unreferenced automatic resources.
          */
         Scope unrefdResources;
@@ -1296,8 +1370,8 @@
 
         @Override
         void markDead() {
-            inits.inclRange(firstadr, nextadr);
-            uninits.inclRange(firstadr, nextadr);
+            inits.inclRange(returnadr, nextadr);
+            uninits.inclRange(returnadr, nextadr);
         }
 
         /*-------------- Processing variables ----------------------*/
@@ -1318,11 +1392,7 @@
          *  index into the vars array.
          */
         void newVar(VarSymbol sym) {
-            if (nextadr == vars.length) {
-                VarSymbol[] newvars = new VarSymbol[nextadr * 2];
-                System.arraycopy(vars, 0, newvars, 0, nextadr);
-                vars = newvars;
-            }
+            vars = ArrayUtils.ensureCapacity(vars, nextadr);
             if ((sym.flags() & FINAL) == 0) {
                 sym.flags_field |= EFFECTIVELY_FINAL;
             }
@@ -1556,6 +1626,7 @@
             Bits uninitsPrev = uninits.dup();
             int nextadrPrev = nextadr;
             int firstadrPrev = firstadr;
+            int returnadrPrev = returnadr;
             Lint lintPrev = lint;
 
             lint = lint.augment(tree.sym.annotations);
@@ -1600,6 +1671,7 @@
                 uninits = uninitsPrev;
                 nextadr = nextadrPrev;
                 firstadr = firstadrPrev;
+                returnadr = returnadrPrev;
                 lint = lintPrev;
             }
         }
@@ -1984,6 +2056,35 @@
             scan(tree.def);
         }
 
+        @Override
+        public void visitLambda(JCLambda tree) {
+            Bits prevUninits = uninits;
+            Bits prevInits = inits;
+            int returnadrPrev = returnadr;
+            ListBuffer<AssignPendingExit> prevPending = pendingExits;
+            try {
+                returnadr = nextadr;
+                pendingExits = new ListBuffer<AssignPendingExit>();
+                for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
+                    JCVariableDecl def = l.head;
+                    scan(def);
+                    inits.incl(def.sym.adr);
+                    uninits.excl(def.sym.adr);
+                }
+                if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
+                    scanExpr(tree.body);
+                } else {
+                    scan(tree.body);
+                }
+            }
+            finally {
+                returnadr = returnadrPrev;
+                uninits = prevUninits;
+                inits = prevInits;
+                pendingExits = prevPending;
+            }
+        }
+
         public void visitNewArray(JCNewArray tree) {
             scanExprs(tree.dims);
             scanExprs(tree.elems);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Oct 11 17:00:54 2012 -0700
@@ -25,18 +25,24 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
+import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
+import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
+import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.util.*;
 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.Symbol.*;
-import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
-import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
 import static com.sun.tools.javac.code.TypeTags.*;
 
 /** Helper class for type parameter inference, used by the attribution phase.
@@ -57,6 +63,7 @@
     Types types;
     Check chk;
     Resolve rs;
+    DeferredAttr deferredAttr;
     Log log;
     JCDiagnostic.Factory diags;
 
@@ -72,55 +79,54 @@
         syms = Symtab.instance(context);
         types = Types.instance(context);
         rs = Resolve.instance(context);
+        deferredAttr = DeferredAttr.instance(context);
         log = Log.instance(context);
         chk = Check.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         inferenceException = new InferenceException(diags);
-
     }
 
+   /**
+    * This exception class is design to store a list of diagnostics corresponding
+    * to inference errors that can arise during a method applicability check.
+    */
     public static class InferenceException extends InapplicableMethodException {
         private static final long serialVersionUID = 0;
 
+        List<JCDiagnostic> messages = List.nil();
+
         InferenceException(JCDiagnostic.Factory diags) {
             super(diags);
         }
+
+        @Override
+        InapplicableMethodException setMessage(JCDiagnostic diag) {
+            messages = messages.append(diag);
+            return this;
+        }
+
+        @Override
+        public JCDiagnostic getDiagnostic() {
+            return messages.head;
+        }
+
+        void clear() {
+            messages = List.nil();
+        }
     }
 
     private final InferenceException inferenceException;
 
 /***************************************************************************
- * Auxiliary type values and classes
- ***************************************************************************/
-
-    /** A mapping that turns type variables into undetermined type variables.
-     */
-    List<Type> makeUndetvars(List<Type> tvars) {
-        List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
-        for (Type t : undetvars) {
-            UndetVar uv = (UndetVar)t;
-            uv.hibounds = types.getBounds((TypeVar)uv.qtype);
-        }
-        return undetvars;
-    }
-    //where
-            Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
-                public Type apply(Type t) {
-                    if (t.tag == TYPEVAR) return new UndetVar(t);
-                    else return t.map(this);
-                }
-            };
-
-/***************************************************************************
  * Mini/Maximization of UndetVars
  ***************************************************************************/
 
     /** Instantiate undetermined type variable to its minimal upper bound.
      *  Throw a NoInstanceException if this not possible.
      */
-    void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
-        List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
-        if (that.eq.isEmpty()) {
+   void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
+        List<Type> hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter);
+        if (that.getBounds(InferenceBound.EQ).isEmpty()) {
             if (hibounds.isEmpty())
                 that.inst = syms.objectType;
             else if (hibounds.tail.isEmpty())
@@ -128,7 +134,7 @@
             else
                 that.inst = types.glb(hibounds);
         } else {
-            that.inst = that.eq.head;
+            that.inst = that.getBounds(InferenceBound.EQ).head;
         }
         if (that.inst == null ||
             that.inst.isErroneous())
@@ -137,10 +143,10 @@
                             that.qtype, hibounds);
     }
 
-    private Filter<Type> errorFilter = new Filter<Type>() {
+    private Filter<Type> boundFilter = new Filter<Type>() {
         @Override
         public boolean accepts(Type t) {
-            return !t.isErroneous();
+            return !t.isErroneous() && t.tag != BOT;
         }
     };
 
@@ -148,11 +154,12 @@
      *  Throw a NoInstanceException if this not possible.
      */
     void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
-        List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
-        if (that.eq.isEmpty()) {
-            if (lobounds.isEmpty())
-                that.inst = syms.botType;
-            else if (lobounds.tail.isEmpty())
+        List<Type> lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter);
+        if (that.getBounds(InferenceBound.EQ).isEmpty()) {
+            if (lobounds.isEmpty()) {
+                //do nothing - the inference variable is under-constrained
+                return;
+            } else if (lobounds.tail.isEmpty())
                 that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
             else {
                 that.inst = types.lub(lobounds);
@@ -162,120 +169,99 @@
                         .setMessage("no.unique.minimal.instance.exists",
                                     that.qtype, lobounds);
         } else {
-            that.inst = that.eq.head;
+            that.inst = that.getBounds(InferenceBound.EQ).head;
         }
     }
 
-    Type asUndetType(Type t, List<Type> undetvars) {
-        return types.subst(t, inferenceVars(undetvars), undetvars);
-    }
-
-    List<Type> inferenceVars(List<Type> undetvars) {
-        ListBuffer<Type> tvars = ListBuffer.lb();
-        for (Type uv : undetvars) {
-            tvars.append(((UndetVar)uv).qtype);
-        }
-        return tvars.toList();
-    }
-
 /***************************************************************************
  * 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.
+    /**
+     * Instantiate uninferred inference variables (JLS 15.12.2.8). First
+     * if the method return type is non-void, we derive constraints from the
+     * expected type - then we use declared bound well-formedness to derive additional
+     * constraints. If no instantiation exists, or if several incomparable
+     * best instantiations exist throw a NoInstanceException.
      */
-    public List<Type> instantiateUninferred(DiagnosticPosition pos,
-                                List<Type> undetvars,
-                                List<Type> tvars,
-                                MethodType mtype,
-                                Attr.ResultInfo resultInfo,
-                                Warner warn) throws InferenceException {
+    public void instantiateUninferred(DiagnosticPosition pos,
+            InferenceContext inferenceContext,
+            MethodType mtype,
+            Attr.ResultInfo resultInfo,
+            Warner warn) throws InferenceException {
         Type to = resultInfo.pt;
-        if (to.tag == NONE) {
+        if (to.tag == NONE || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
             to = mtype.getReturnType().tag <= VOID ?
                     mtype.getReturnType() : syms.objectType;
         }
-        Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
+        Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
         if (!types.isSubtype(qtype1,
                 qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
             throw inferenceException
-                .setMessage("infer.no.conforming.instance.exists",
-                            tvars, mtype.getReturnType(), to);
+                    .setMessage("infer.no.conforming.instance.exists",
+                    inferenceContext.restvars(), mtype.getReturnType(), to);
         }
 
-        List<Type> insttypes;
         while (true) {
             boolean stuck = true;
-            insttypes = List.nil();
-            for (Type t : undetvars) {
+            for (Type t : inferenceContext.undetvars) {
                 UndetVar uv = (UndetVar)t;
-                if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
+                if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() ||
+                        !inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) {
                     maximizeInst((UndetVar)t, warn);
                     stuck = false;
                 }
-                insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
             }
-            if (!Type.containsAny(insttypes, tvars)) {
+            if (inferenceContext.restvars().isEmpty()) {
                 //all variables have been instantiated - exit
                 break;
             } else if (stuck) {
                 //some variables could not be instantiated because of cycles in
                 //upper bounds - provide a (possibly recursive) default instantiation
-                insttypes = types.subst(insttypes,
-                    tvars,
-                    instantiateAsUninferredVars(undetvars, tvars));
+                instantiateAsUninferredVars(inferenceContext);
                 break;
             } else {
                 //some variables have been instantiated - replace newly instantiated
                 //variables in remaining upper bounds and continue
-                for (Type t : undetvars) {
+                for (Type t : inferenceContext.undetvars) {
                     UndetVar uv = (UndetVar)t;
-                    uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
+                    uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
                 }
             }
         }
-        return insttypes;
     }
 
     /**
      * Infer cyclic inference variables as described in 15.12.2.8.
      */
-    private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
-        Assert.check(undetvars.length() == tvars.length());
-        ListBuffer<Type> insttypes = ListBuffer.lb();
+    private void instantiateAsUninferredVars(InferenceContext inferenceContext) {
         ListBuffer<Type> todo = ListBuffer.lb();
         //step 1 - create fresh tvars
-        for (Type t : undetvars) {
+        for (Type t : inferenceContext.undetvars) {
             UndetVar uv = (UndetVar)t;
             if (uv.inst == null) {
                 TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
-                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
+                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
                 todo.append(uv);
                 uv.inst = fresh_tvar.type;
             }
-            insttypes.append(uv.inst);
         }
         //step 2 - replace fresh tvars in their bounds
-        List<Type> formals = tvars;
+        List<Type> formals = inferenceContext.inferenceVars();
         for (Type t : todo) {
             UndetVar uv = (UndetVar)t;
             TypeVar ct = (TypeVar)uv.inst;
-            ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
+            ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct), types));
             if (ct.bound.isErroneous()) {
                 //report inference error if glb fails
                 reportBoundError(uv, BoundErrorKind.BAD_UPPER);
             }
             formals = formals.tail;
         }
-        return insttypes.toList();
     }
 
-    /** Instantiate method type `mt' by finding instantiations of
-     *  `tvars' so that method can be applied to `argtypes'.
+    /** Instantiate a generic method type by finding instantiations for all its
+     * inference variables so that it can be applied to a given argument type list.
      */
     public Type instantiateMethod(Env<AttrContext> env,
                                   List<Type> tvars,
@@ -285,85 +271,65 @@
                                   List<Type> argtypes,
                                   boolean allowBoxing,
                                   boolean useVarargs,
+                                  Resolve.MethodResolutionContext resolveContext,
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
-        List<Type> undetvars =  makeUndetvars(tvars);
+        final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
+        inferenceException.clear();
 
-        List<Type> capturedArgs =
-                rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
-                    allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
+        try {
+            rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
+                    argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
+                    new InferenceCheckHandler(inferenceContext));
 
-        // minimize as yet undetermined type variables
-        for (Type t : undetvars)
-            minimizeInst((UndetVar) t, warn);
+            // minimize as yet undetermined type variables
+            for (Type t : inferenceContext.undetvars) {
+                minimizeInst((UndetVar)t, warn);
+            }
 
-        /** Type variables instantiated to bottom */
-        ListBuffer<Type> restvars = new ListBuffer<Type>();
+            checkWithinBounds(inferenceContext, warn);
 
-        /** Undet vars instantiated to bottom */
-        final ListBuffer<Type> restundet = new ListBuffer<Type>();
+            mt = (MethodType)inferenceContext.asInstType(mt, types);
 
-        /** Instantiated types or TypeVars if under-constrained */
-        ListBuffer<Type> insttypes = new ListBuffer<Type>();
+            List<Type> restvars = inferenceContext.restvars();
 
-        /** Instantiated types or UndetVars if under-constrained */
-        ListBuffer<Type> undettypes = new ListBuffer<Type>();
+            if (!restvars.isEmpty()) {
+                if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
+                    instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
+                    checkWithinBounds(inferenceContext, warn);
+                    mt = (MethodType)inferenceContext.asInstType(mt, types);
+                    if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
+                        log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
+                    }
+                }
+            }
 
-        for (Type t : undetvars) {
-            UndetVar uv = (UndetVar)t;
-            if (uv.inst.tag == BOT) {
-                restvars.append(uv.qtype);
-                restundet.append(uv);
-                insttypes.append(uv.qtype);
-                undettypes.append(uv);
-                uv.inst = null;
-            } else {
-                insttypes.append(uv.inst);
-                undettypes.append(uv.inst);
-            }
+            // return instantiated version of method type
+            return mt;
+        } finally {
+            inferenceContext.notifyChange(types);
         }
-        checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
-
-        mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
-
-        if (!restvars.isEmpty() && resultInfo != null) {
-            List<Type> restInferred =
-                    instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
-            checkWithinBounds(tvars, undetvars,
-                           types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
-            mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
-            if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
-                log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
-            }
-        }
-
-        if (restvars.isEmpty() || resultInfo != null) {
-            // check that actuals conform to inferred formals
-            checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
-        }
-        // return instantiated version of method type
-        return mt;
     }
     //where
 
         /** inference check handler **/
         class InferenceCheckHandler implements Resolve.MethodCheckHandler {
 
-            List<Type> undetvars;
+            InferenceContext inferenceContext;
 
-            public InferenceCheckHandler(List<Type> undetvars) {
-                this.undetvars = undetvars;
+            public InferenceCheckHandler(InferenceContext inferenceContext) {
+                this.inferenceContext = inferenceContext;
             }
 
             public InapplicableMethodException arityMismatch() {
-                return inferenceException.setMessage("infer.arg.length.mismatch", inferenceVars(undetvars));
+                return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
             }
             public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
                 String key = varargs ?
                         "infer.varargs.argument.mismatch" :
                         "infer.no.conforming.assignment.exists";
                 return inferenceException.setMessage(key,
-                        inferenceVars(undetvars), details);
+                        inferenceContext.inferenceVars(), details);
             }
             public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
                 return inferenceException.setMessage("inaccessible.varargs.type",
@@ -371,51 +337,61 @@
             }
         }
 
-        private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
-                boolean allowBoxing, boolean useVarargs, Warner warn) {
-            try {
-                rs.checkRawArgumentsAcceptable(env, actuals, formals,
-                       allowBoxing, useVarargs, warn);
-            }
-            catch (InapplicableMethodException ex) {
-                // inferred method is not applicable
-                throw inferenceException.setMessage(ex.getDiagnostic());
-            }
-        }
-
     /** check that type parameters are within their bounds.
      */
-    void checkWithinBounds(List<Type> tvars,
-                           List<Type> undetvars,
-                           List<Type> arguments,
-                           Warner warn)
-        throws InferenceException {
-        List<Type> args = arguments;
-        for (Type t : undetvars) {
+    void checkWithinBounds(InferenceContext inferenceContext,
+                           Warner warn) throws InferenceException {
+        //step 1 - check compatibility of instantiated type w.r.t. initial bounds
+        for (Type t : inferenceContext.undetvars) {
             UndetVar uv = (UndetVar)t;
-            uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
-            uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
-            uv.eq = types.subst(uv.eq, tvars, arguments);
-            checkCompatibleUpperBounds(uv, tvars);
-            if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
-                Type inst = args.head;
-                for (Type u : uv.hibounds) {
-                    if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
+            uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
+            checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
+            if (!inferenceContext.restvars().contains(uv.qtype)) {
+                Type inst = inferenceContext.asInstType(t, types);
+                for (Type u : uv.getBounds(InferenceBound.UPPER)) {
+                    if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
                         reportBoundError(uv, BoundErrorKind.UPPER);
                     }
                 }
-                for (Type l : uv.lobounds) {
-                    if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
+                for (Type l : uv.getBounds(InferenceBound.LOWER)) {
+                    Assert.check(!inferenceContext.free(l));
+                    if (!types.isSubtypeUnchecked(l, inst, warn)) {
                         reportBoundError(uv, BoundErrorKind.LOWER);
                     }
                 }
-                for (Type e : uv.eq) {
-                    if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
+                for (Type e : uv.getBounds(InferenceBound.EQ)) {
+                    Assert.check(!inferenceContext.free(e));
+                    if (!types.isSameType(inst, e)) {
                         reportBoundError(uv, BoundErrorKind.EQ);
                     }
                 }
             }
-            args = args.tail;
+        }
+
+        //step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds
+        for (Type t : inferenceContext.undetvars) {
+            UndetVar uv = (UndetVar)t;
+            //check eq bounds consistency
+            Type eq = null;
+            for (Type e : uv.getBounds(InferenceBound.EQ)) {
+                Assert.check(!inferenceContext.free(e));
+                if (eq != null && !types.isSameType(e, eq)) {
+                    reportBoundError(uv, BoundErrorKind.EQ);
+                }
+                eq = e;
+                for (Type l : uv.getBounds(InferenceBound.LOWER)) {
+                    Assert.check(!inferenceContext.free(l));
+                    if (!types.isSubtypeUnchecked(l, e, warn)) {
+                        reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
+                    }
+                }
+                for (Type u : uv.getBounds(InferenceBound.UPPER)) {
+                    if (inferenceContext.free(u)) continue;
+                    if (!types.isSubtypeUnchecked(e, u, warn)) {
+                        reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
+                    }
+                }
+            }
         }
     }
 
@@ -423,7 +399,7 @@
         // VGJ: sort of inlined maximizeInst() below.  Adding
         // bounds can cause lobounds that are above hibounds.
         ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
-        for (Type t : Type.filter(uv.hibounds, errorFilter)) {
+        for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) {
             if (!t.containsAny(tvars)) {
                 hiboundsNoVars.append(t);
             }
@@ -444,25 +420,43 @@
         BAD_UPPER() {
             @Override
             InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
-                return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds);
+                return ex.setMessage("incompatible.upper.bounds", uv.qtype,
+                        uv.getBounds(InferenceBound.UPPER));
+            }
+        },
+        BAD_EQ_UPPER() {
+            @Override
+            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
+                return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype,
+                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER));
+            }
+        },
+        BAD_EQ_LOWER() {
+            @Override
+            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
+                return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype,
+                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER));
             }
         },
         UPPER() {
             @Override
             InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
-                return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds);
+                return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst,
+                        uv.getBounds(InferenceBound.UPPER));
             }
         },
         LOWER() {
             @Override
             InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
-                return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds);
+                return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst,
+                        uv.getBounds(InferenceBound.LOWER));
             }
         },
         EQ() {
             @Override
             InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
-                return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq);
+                return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst,
+                        uv.getBounds(InferenceBound.EQ));
             }
         };
 
@@ -473,6 +467,75 @@
         throw bk.setMessage(inferenceException, uv);
     }
 
+    // <editor-fold desc="functional interface instantiation">
+    /**
+     * This method is used to infer a suitable target functional interface in case
+     * the original parameterized interface contains 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 instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
+            List<Type> paramTypes, Check.CheckContext checkContext) {
+        if (types.capture(funcInterface) == funcInterface) {
+            //if capture doesn't change the type then return the target unchanged
+            //(this means the target contains no wildcards!)
+            return funcInterface;
+        } else {
+            Type formalInterface = funcInterface.tsym.type;
+            InferenceContext funcInterfaceContext =
+                    new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
+            if (paramTypes != null) {
+                //get constraints from explicit params (this is done by
+                //checking that explicit param types are equal to the ones
+                //in the functional interface descriptors)
+                List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
+                if (descParameterTypes.size() != paramTypes.size()) {
+                    checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
+                    return types.createErrorType(funcInterface);
+                }
+                for (Type p : descParameterTypes) {
+                    if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
+                        checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
+                        return types.createErrorType(funcInterface);
+                    }
+                    paramTypes = paramTypes.tail;
+                }
+                for (Type t : funcInterfaceContext.undetvars) {
+                    UndetVar uv = (UndetVar)t;
+                    minimizeInst(uv, Warner.noWarnings);
+                    if (uv.inst == null &&
+                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
+                        maximizeInst(uv, Warner.noWarnings);
+                    }
+                }
+
+                formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
+            }
+            ListBuffer<Type> typeargs = ListBuffer.lb();
+            List<Type> actualTypeargs = funcInterface.getTypeArguments();
+            //for remaining uninferred type-vars in the functional interface type,
+            //simply replace the wildcards with its bound
+            for (Type t : formalInterface.getTypeArguments()) {
+                if (actualTypeargs.head.tag == WILDCARD) {
+                    WildcardType wt = (WildcardType)actualTypeargs.head;
+                    typeargs.append(wt.type);
+                } else {
+                    typeargs.append(actualTypeargs.head);
+                }
+                actualTypeargs = actualTypeargs.tail;
+            }
+            Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
+            if (!chk.checkValidGenericType(owntype)) {
+                //if the inferred functional interface type is not well-formed,
+                //or if it's not a subtype of the original target, issue an error
+                checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
+                return types.createErrorType(funcInterface);
+            }
+            return owntype;
+        }
+    }
+    // </editor-fold>
+
     /**
      * Compute a synthetic method type corresponding to the requested polymorphic
      * method signature. The target return type is computed from the immediately
@@ -480,6 +543,7 @@
      */
     Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env,
                                             MethodSymbol spMethod,  // sig. poly. method or null if none
+                                            Resolve.MethodResolutionContext resolveContext,
                                             List<Type> argtypes) {
         final Type restype;
 
@@ -509,7 +573,7 @@
                 restype = syms.objectType;
         }
 
-        List<Type> paramtypes = Type.map(argtypes, implicitArgType);
+        List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step));
         List<Type> exType = spMethod != null ?
             spMethod.getThrownTypes() :
             List.of(syms.throwableType); // make it throw all exceptions
@@ -521,14 +585,234 @@
         return mtype;
     }
     //where
-        Mapping implicitArgType = new Mapping ("implicitArgType") {
-                public Type apply(Type t) {
-                    t = types.erasure(t);
-                    if (t.tag == BOT)
-                        // nulls type as the marker type Null (which has no instances)
-                        // infer as java.lang.Void for now
-                        t = types.boxedClass(syms.voidType).type;
-                    return t;
+        class ImplicitArgType extends DeferredAttr.DeferredTypeMap {
+
+            public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
+                deferredAttr.super(AttrMode.SPECULATIVE, msym, phase);
+            }
+
+            public Type apply(Type t) {
+                t = types.erasure(super.apply(t));
+                if (t.tag == BOT)
+                    // nulls type as the marker type Null (which has no instances)
+                    // infer as java.lang.Void for now
+                    t = types.boxedClass(syms.voidType).type;
+                return t;
+            }
+        }
+
+    /**
+     * Mapping that turns inference variables into undet vars
+     * (used by inference context)
+     */
+    class FromTypeVarFun extends Mapping {
+
+        boolean includeBounds;
+
+        FromTypeVarFun(boolean includeBounds) {
+            super("fromTypeVarFunWithBounds");
+            this.includeBounds = includeBounds;
+        }
+
+        public Type apply(Type t) {
+            if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types, includeBounds);
+            else return t.map(this);
+        }
+    };
+
+    /**
+     * An inference context keeps track of the set of variables that are free
+     * in the current context. It provides utility methods for opening/closing
+     * types to their corresponding free/closed forms. It also provide hooks for
+     * attaching deferred post-inference action (see PendingCheck). Finally,
+     * it can be used as an entry point for performing upper/lower bound inference
+     * (see InferenceKind).
+     */
+    static class InferenceContext {
+
+        /**
+        * Single-method-interface for defining inference callbacks. Certain actions
+        * (i.e. subtyping checks) might need to be redone after all inference variables
+        * have been fixed.
+        */
+        interface FreeTypeListener {
+            void typesInferred(InferenceContext inferenceContext);
+        }
+
+        /** list of inference vars as undet vars */
+        List<Type> undetvars;
+
+        /** list of inference vars in this context */
+        List<Type> inferencevars;
+
+        java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
+                new java.util.HashMap<FreeTypeListener, List<Type>>();
+
+        List<FreeTypeListener> freetypeListeners = List.nil();
+
+        public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) {
+            this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds));
+            this.inferencevars = inferencevars;
+        }
+
+        /**
+         * returns the list of free variables (as type-variables) in this
+         * inference context
+         */
+        List<Type> inferenceVars() {
+            return inferencevars;
+        }
+
+        /**
+         * returns the list of uninstantiated variables (as type-variables) in this
+         * inference context (usually called after instantiate())
+         */
+        List<Type> restvars() {
+            List<Type> undetvars = this.undetvars;
+            ListBuffer<Type> restvars = ListBuffer.lb();
+            for (Type t : instTypes()) {
+                UndetVar uv = (UndetVar)undetvars.head;
+                if (uv.qtype == t) {
+                    restvars.append(t);
                 }
-        };
+                undetvars = undetvars.tail;
+            }
+            return restvars.toList();
+        }
+
+        /**
+         * is this type free?
+         */
+        final boolean free(Type t) {
+            return t.containsAny(inferencevars);
+        }
+
+        final boolean free(List<Type> ts) {
+            for (Type t : ts) {
+                if (free(t)) return true;
+            }
+            return false;
+        }
+
+        /**
+         * Returns a list of free variables in a given type
+         */
+        final List<Type> freeVarsIn(Type t) {
+            ListBuffer<Type> buf = ListBuffer.lb();
+            for (Type iv : inferenceVars()) {
+                if (t.contains(iv)) {
+                    buf.add(iv);
+                }
+            }
+            return buf.toList();
+        }
+
+        final List<Type> freeVarsIn(List<Type> ts) {
+            ListBuffer<Type> buf = ListBuffer.lb();
+            for (Type t : ts) {
+                buf.appendList(freeVarsIn(t));
+            }
+            ListBuffer<Type> buf2 = ListBuffer.lb();
+            for (Type t : buf) {
+                if (!buf2.contains(t)) {
+                    buf2.add(t);
+                }
+            }
+            return buf2.toList();
+        }
+
+        /**
+         * Replace all free variables in a given type with corresponding
+         * undet vars (used ahead of subtyping/compatibility checks to allow propagation
+         * of inference constraints).
+         */
+        final Type asFree(Type t, Types types) {
+            return types.subst(t, inferencevars, undetvars);
+        }
+
+        final List<Type> asFree(List<Type> ts, Types types) {
+            ListBuffer<Type> buf = ListBuffer.lb();
+            for (Type t : ts) {
+                buf.append(asFree(t, types));
+            }
+            return buf.toList();
+        }
+
+        List<Type> instTypes() {
+            ListBuffer<Type> buf = ListBuffer.lb();
+            for (Type t : undetvars) {
+                UndetVar uv = (UndetVar)t;
+                buf.append(uv.inst != null ? uv.inst : uv.qtype);
+            }
+            return buf.toList();
+        }
+
+        /**
+         * Replace all free variables in a given type with corresponding
+         * instantiated types - if one or more free variable has not been
+         * fully instantiated, it will still be available in the resulting type.
+         */
+        Type asInstType(Type t, Types types) {
+            return types.subst(t, inferencevars, instTypes());
+        }
+
+        List<Type> asInstTypes(List<Type> ts, Types types) {
+            ListBuffer<Type> buf = ListBuffer.lb();
+            for (Type t : ts) {
+                buf.append(asInstType(t, types));
+            }
+            return buf.toList();
+        }
+
+        /**
+         * Add custom hook for performing post-inference action
+         */
+        void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) {
+            freeTypeListeners.put(ftl, freeVarsIn(types));
+        }
+
+        /**
+         * Mark the inference context as complete and trigger evaluation
+         * of all deferred checks.
+         */
+        void notifyChange(Types types) {
+            InferenceException thrownEx = null;
+            for (Map.Entry<FreeTypeListener, List<Type>> entry :
+                    new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
+                if (!Type.containsAny(entry.getValue(), restvars())) {
+                    try {
+                        entry.getKey().typesInferred(this);
+                        freeTypeListeners.remove(entry.getKey());
+                    } catch (InferenceException ex) {
+                        if (thrownEx == null) {
+                            thrownEx = ex;
+                        }
+                    }
+                }
+            }
+            //inference exception multiplexing - present any inference exception
+            //thrown when processing listeners as a single one
+            if (thrownEx != null) {
+                throw thrownEx;
+            }
+        }
+
+        void solveAny(List<Type> varsToSolve, Types types, Infer infer) {
+            boolean progress = false;
+            for (Type t : varsToSolve) {
+                UndetVar uv = (UndetVar)asFree(t, types);
+                if (uv.inst == null) {
+                    infer.minimizeInst(uv, Warner.noWarnings);
+                    if (uv.inst != null) {
+                        progress = true;
+                    }
+                }
+            }
+            if (!progress) {
+                throw infer.inferenceException.setMessage("cyclic.inference", varsToSolve);
+            }
+        }
     }
+
+    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false);
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1998,7 +1998,7 @@
             // replace with <BoxedClass>.TYPE
             ClassSymbol c = types.boxedClass(type);
             Symbol typeSym =
-                rs.access(
+                rs.accessBase(
                     rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR),
                     pos, c.type, names.TYPE, true);
             if (typeSym.kind == VAR)
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -604,6 +604,10 @@
             env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));
         localEnv.enclMethod = tree;
         localEnv.info.scope.owner = tree.sym;
+        if (tree.sym.type != null) {
+            //when this is called in the enter stage, there's no type to be set
+            localEnv.info.returnResult = attr.new ResultInfo(VAL, tree.sym.type.getReturnType());
+        }
         if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
         return localEnv;
     }
@@ -642,7 +646,9 @@
         tree.sym = v;
         if (tree.init != null) {
             v.flags_field |= HASINIT;
-            if ((v.flags_field & FINAL) != 0 && !tree.init.hasTag(NEWCLASS)) {
+            if ((v.flags_field & FINAL) != 0 &&
+                    !tree.init.hasTag(NEWCLASS) &&
+                    !tree.init.hasTag(LAMBDA)) {
                 Env<AttrContext> initEnv = getInitEnv(tree, env);
                 initEnv.info.enclVar = v;
                 v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init);
@@ -667,7 +673,7 @@
     Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
         Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup()));
         if (tree.sym.owner.kind == TYP) {
-            localEnv.info.scope = new Scope.DelegatedScope(env.info.scope);
+            localEnv.info.scope = env.info.scope.dupUnshared();
             localEnv.info.scope.owner = tree.sym;
         }
         if ((tree.mods.flags & STATIC) != 0 ||
@@ -970,9 +976,11 @@
                 List<Type> thrown = List.nil();
                 long ctorFlags = 0;
                 boolean based = false;
+                boolean addConstructor = true;
                 if (c.name.isEmpty()) {
                     JCNewClass nc = (JCNewClass)env.next.tree;
                     if (nc.constructor != null) {
+                        addConstructor = nc.constructor.kind != ERR;
                         Type superConstrType = types.memberType(c.type,
                                                                 nc.constructor);
                         argtypes = superConstrType.getParameterTypes();
@@ -985,10 +993,12 @@
                         thrown = superConstrType.getThrownTypes();
                     }
                 }
-                JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
-                                                    typarams, argtypes, thrown,
-                                                    ctorFlags, based);
-                tree.defs = tree.defs.prepend(constrDef);
+                if (addConstructor) {
+                    JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
+                                                        typarams, argtypes, thrown,
+                                                        ctorFlags, based);
+                    tree.defs = tree.defs.prepend(constrDef);
+                }
             }
 
             // If this is a class, enter symbols for this and super into
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Oct 11 17:00:54 2012 -0700
@@ -27,14 +27,20 @@
 
 import com.sun.tools.javac.api.Formattable.LocalizedString;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.Attr.ResultInfo;
 import com.sun.tools.javac.comp.Check.CheckContext;
+import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
+import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
+import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -44,9 +50,8 @@
 import java.util.Collection;
 import java.util.EnumMap;
 import java.util.EnumSet;
-import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 import javax.lang.model.element.ElementVisitor;
 
@@ -73,6 +78,7 @@
     Log log;
     Symtab syms;
     Attr attr;
+    DeferredAttr deferredAttr;
     Check chk;
     Infer infer;
     ClassReader reader;
@@ -93,10 +99,6 @@
 
         varNotFound = new
             SymbolNotFoundError(ABSENT_VAR);
-        wrongMethod = new
-            InapplicableSymbolError();
-        wrongMethods = new
-            InapplicableSymbolsError();
         methodNotFound = new
             SymbolNotFoundError(ABSENT_MTH);
         typeNotFound = new
@@ -105,6 +107,7 @@
         names = Names.instance(context);
         log = Log.instance(context);
         attr = Attr.instance(context);
+        deferredAttr = DeferredAttr.instance(context);
         chk = Check.instance(context);
         infer = Infer.instance(context);
         reader = ClassReader.instance(context);
@@ -127,8 +130,6 @@
     /** error symbols, which are returned when resolution fails
      */
     private final SymbolNotFoundError varNotFound;
-    private final InapplicableSymbolError wrongMethod;
-    private final InapplicableSymbolsError wrongMethods;
     private final SymbolNotFoundError methodNotFound;
     private final SymbolNotFoundError typeNotFound;
 
@@ -215,9 +216,12 @@
             }
         }
         String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
+        List<Type> argtypes2 = Type.map(argtypes,
+                    deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
         JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
                 site.tsym, mostSpecificPos, currentResolutionContext.step,
-                methodArguments(argtypes), methodArguments(typeargtypes));
+                methodArguments(argtypes2),
+                methodArguments(typeargtypes));
         JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
         log.report(d);
     }
@@ -247,7 +251,7 @@
     /** An environment is "static" if its static level is greater than
      *  the one of its outer environment
      */
-    static boolean isStatic(Env<AttrContext> env) {
+    protected static boolean isStatic(Env<AttrContext> env) {
         return env.info.staticLevel > env.outer.info.staticLevel;
     }
 
@@ -445,8 +449,18 @@
                         boolean useVarargs,
                         Warner warn)
         throws Infer.InferenceException {
-        if (useVarargs && (m.flags() & VARARGS) == 0)
-            throw inapplicableMethodException.setMessage();
+        if (useVarargs && (m.flags() & VARARGS) == 0) {
+            //better error recovery - if we stumbled upon a non-varargs method
+            //during varargs applicability phase, the method should be treated as
+            //not applicable; the reason for inapplicability can be found in the
+            //candidate for 'm' that was created during the BOX phase.
+            Candidate prevCandidate = currentResolutionContext.getCandidate(m, BOX);
+            JCDiagnostic details = null;
+            if (prevCandidate != null && !prevCandidate.isApplicable()) {
+                details = prevCandidate.details;
+            }
+            throw inapplicableMethodException.setMessage(details);
+        }
         Type mt = types.memberType(site, m);
 
         // tvars is the list of formal type variables for which type arguments
@@ -497,13 +511,34 @@
                                     argtypes,
                                     allowBoxing,
                                     useVarargs,
+                                    currentResolutionContext,
                                     warn);
 
-        checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(),
+        checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(),
                                 allowBoxing, useVarargs, warn);
         return mt;
     }
 
+    Type checkMethod(Env<AttrContext> env,
+                     Type site,
+                     Symbol m,
+                     ResultInfo resultInfo,
+                     List<Type> argtypes,
+                     List<Type> typeargtypes,
+                     Warner warn) {
+        MethodResolutionContext prevContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
+            MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
+            return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
+                    step.isBoxingRequired(), step.isVarargsRequired(), warn);
+        }
+        finally {
+            currentResolutionContext = prevContext;
+        }
+    }
+
     /** Same but returns null instead throwing a NoInstanceException
      */
     Type instantiate(Env<AttrContext> env,
@@ -526,13 +561,14 @@
     /** Check if a parameter list accepts a list of args.
      */
     boolean argumentsAcceptable(Env<AttrContext> env,
+                                Symbol msym,
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn) {
         try {
-            checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn);
+            checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn);
             return true;
         } catch (InapplicableMethodException ex) {
             return false;
@@ -579,12 +615,13 @@
     };
 
     void checkRawArgumentsAcceptable(Env<AttrContext> env,
+                                Symbol msym,
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn) {
-        checkRawArgumentsAcceptable(env, List.<Type>nil(), argtypes, formals,
+        checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
                 allowBoxing, useVarargs, warn, resolveHandler);
     }
 
@@ -594,35 +631,41 @@
      * 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.
+     * type-inference, a (possibly empty) inference context is used to convert
+     * formal types to the corresponding 'undet' form ahead of a compatibility
+     * check 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).
+     * Moreover, if one or more types in A is a deferred type, this routine uses
+     * DeferredAttr in order to perform deferred attribution. If one or more actual
+     * deferred types are stuck, they are placed in a queue and revisited later
+     * after the remainder of the arguments have been seen. If this is not sufficient
+     * to 'unstuck' the argument, a cyclic inference error is called out.
      *
      * A method check handler (see above) is used in order to report errors.
      */
-    List<Type> checkRawArgumentsAcceptable(Env<AttrContext> env,
-                                List<Type> undetvars,
+    void checkRawArgumentsAcceptable(final Env<AttrContext> env,
+                                Symbol msym,
+                                DeferredAttr.AttrMode mode,
+                                final Infer.InferenceContext inferenceContext,
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn,
-                                MethodCheckHandler handler) {
+                                final MethodCheckHandler handler) {
         Type varargsFormal = useVarargs ? formals.last() : null;
-        ListBuffer<Type> checkedArgs = ListBuffer.lb();
 
         if (varargsFormal == null &&
                 argtypes.size() != formals.size()) {
             throw handler.arityMismatch(); // not enough args
         }
 
+        DeferredAttr.DeferredAttrContext deferredAttrContext =
+                deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext);
+
         while (argtypes.nonEmpty() && formals.head != varargsFormal) {
-            ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, undetvars, handler, warn);
-            checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
+            ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn);
+            mresult.check(null, argtypes.head);
             argtypes = argtypes.tail;
             formals = formals.tail;
         }
@@ -634,19 +677,33 @@
         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.elemtype(varargsFormal);
+            final Type elt = types.elemtype(varargsFormal);
+            ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn);
             while (argtypes.nonEmpty()) {
-                ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, undetvars, handler, warn);
-                checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head));
+                mresult.check(null, argtypes.head);
                 argtypes = argtypes.tail;
             }
             //check varargs element type accessibility
-            if (undetvars.isEmpty() && !isAccessible(env, elt)) {
+            varargsAccessible(env, elt, handler, inferenceContext);
+        }
+
+        deferredAttrContext.complete();
+    }
+
+    void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
+        if (inferenceContext.free(t)) {
+            inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
+                @Override
+                public void typesInferred(InferenceContext inferenceContext) {
+                    varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
+                }
+            });
+        } else {
+            if (!isAccessible(env, t)) {
                 Symbol location = env.enclClass.sym;
-                throw handler.inaccessibleVarargs(location, elt);
+                throw handler.inaccessibleVarargs(location, t);
             }
         }
-        return checkedArgs.toList();
     }
 
     /**
@@ -657,13 +714,16 @@
 
         MethodCheckHandler handler;
         boolean useVarargs;
-        List<Type> undetvars;
+        Infer.InferenceContext inferenceContext;
+        DeferredAttrContext deferredAttrContext;
         Warner rsWarner;
 
-        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
+        public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs,
+                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
             this.handler = handler;
             this.useVarargs = useVarargs;
-            this.undetvars = undetvars;
+            this.inferenceContext = inferenceContext;
+            this.deferredAttrContext = deferredAttrContext;
             this.rsWarner = rsWarner;
         }
 
@@ -674,6 +734,14 @@
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
             return rsWarner;
         }
+
+        public InferenceContext inferenceContext() {
+            return inferenceContext;
+        }
+
+        public DeferredAttrContext deferredAttrContext() {
+            return deferredAttrContext;
+        }
     }
 
     /**
@@ -682,12 +750,17 @@
      */
     class StrictMethodContext extends MethodCheckContext {
 
-        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
-            super(handler, useVarargs, undetvars, rsWarner);
+        public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs,
+                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
         }
 
         public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isSubtypeUnchecked(found, infer.asUndetType(req, undetvars), warn);
+            return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
+        }
+
+        public boolean allowBoxing() {
+            return false;
         }
     }
 
@@ -697,12 +770,17 @@
      */
     class LooseMethodContext extends MethodCheckContext {
 
-        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, List<Type> undetvars, Warner rsWarner) {
-            super(handler, useVarargs, undetvars, rsWarner);
+        public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs,
+                Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
+            super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
         }
 
         public boolean compatible(Type found, Type req, Warner warn) {
-            return types.isConvertible(found, infer.asUndetType(req, undetvars), warn);
+            return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
+        }
+
+        public boolean allowBoxing() {
+            return true;
         }
     }
 
@@ -710,16 +788,37 @@
      * Create a method check context to be used during method applicability check
      */
     ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
-            List<Type> undetvars, MethodCheckHandler methodHandler, Warner rsWarner) {
+            Infer.InferenceContext inferenceContext, DeferredAttr.DeferredAttrContext deferredAttrContext,
+            MethodCheckHandler methodHandler, Warner rsWarner) {
         MethodCheckContext checkContext = allowBoxing ?
-                new LooseMethodContext(methodHandler, useVarargs, undetvars, rsWarner) :
-                new StrictMethodContext(methodHandler, useVarargs, undetvars, rsWarner);
-        return attr.new ResultInfo(VAL, to, checkContext) {
-            @Override
-            protected Type check(DiagnosticPosition pos, Type found) {
-                return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found))));
+                new LooseMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner) :
+                new StrictMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
+        return new MethodResultInfo(to, checkContext, deferredAttrContext);
+    }
+
+    class MethodResultInfo extends ResultInfo {
+
+        DeferredAttr.DeferredAttrContext deferredAttrContext;
+
+        public MethodResultInfo(Type pt, MethodCheckContext checkContext, DeferredAttr.DeferredAttrContext deferredAttrContext) {
+            attr.super(VAL, pt, checkContext);
+            this.deferredAttrContext = deferredAttrContext;
+        }
+
+        @Override
+        protected Type check(DiagnosticPosition pos, Type found) {
+            if (found.tag == DEFERRED) {
+                DeferredType dt = (DeferredType)found;
+                return dt.check(this);
+            } else {
+                return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found.baseType()))));
             }
-        };
+        }
+
+        @Override
+        protected MethodResultInfo dup(Type newPt) {
+            return new MethodResultInfo(newPt, (MethodCheckContext)checkContext, deferredAttrContext);
+        }
     }
 
     public static class InapplicableMethodException extends RuntimeException {
@@ -733,16 +832,13 @@
             this.diags = diags;
         }
         InapplicableMethodException setMessage() {
-            this.diagnostic = null;
-            return this;
+            return setMessage((JCDiagnostic)null);
         }
         InapplicableMethodException setMessage(String key) {
-            this.diagnostic = key != null ? diags.fragment(key) : null;
-            return this;
+            return setMessage(key != null ? diags.fragment(key) : null);
         }
         InapplicableMethodException setMessage(String key, Object... args) {
-            this.diagnostic = key != null ? diags.fragment(key, args) : null;
-            return this;
+            return setMessage(key != null ? diags.fragment(key, args) : null);
         }
         InapplicableMethodException setMessage(JCDiagnostic diag) {
             this.diagnostic = diag;
@@ -937,11 +1033,10 @@
                 currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
             switch (bestSoFar.kind) {
             case ABSENT_MTH:
-                return wrongMethod;
+                return new InapplicableSymbolError(currentResolutionContext);
             case WRONG_MTH:
                 if (operator) return bestSoFar;
-            case WRONG_MTHS:
-                return wrongMethods;
+                bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
             default:
                 return bestSoFar;
             }
@@ -953,7 +1048,7 @@
         }
         return (bestSoFar.kind > AMBIGUOUS)
             ? sym
-            : mostSpecific(sym, bestSoFar, env, site,
+            : mostSpecific(argtypes, sym, bestSoFar, env, site,
                            allowBoxing && operator, useVarargs);
     }
 
@@ -967,7 +1062,7 @@
      *  @param allowBoxing Allow boxing conversions of arguments.
      *  @param useVarargs Box trailing arguments into an array for varargs.
      */
-    Symbol mostSpecific(Symbol m1,
+    Symbol mostSpecific(List<Type> argtypes, Symbol m1,
                         Symbol m2,
                         Env<AttrContext> env,
                         final Type site,
@@ -976,8 +1071,10 @@
         switch (m2.kind) {
         case MTH:
             if (m1 == m2) return m1;
-            boolean m1SignatureMoreSpecific = signatureMoreSpecific(env, site, m1, m2, allowBoxing, useVarargs);
-            boolean m2SignatureMoreSpecific = signatureMoreSpecific(env, site, m2, m1, allowBoxing, useVarargs);
+            boolean m1SignatureMoreSpecific =
+                    signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
+            boolean m2SignatureMoreSpecific =
+                    signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
             if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
                 Type mt1 = types.memberType(site, m1);
                 Type mt2 = types.memberType(site, m2);
@@ -1035,8 +1132,8 @@
                             return this;
                         else
                             return super.implementation(origin, types, checkResult);
-                    }
-                };
+                        }
+                    };
                 return result;
             }
             if (m1SignatureMoreSpecific) return m1;
@@ -1044,8 +1141,8 @@
             return ambiguityError(m1, m2);
         case AMBIGUOUS:
             AmbiguityError e = (AmbiguityError)m2;
-            Symbol err1 = mostSpecific(m1, e.sym, env, site, allowBoxing, useVarargs);
-            Symbol err2 = mostSpecific(m1, e.sym2, env, site, allowBoxing, useVarargs);
+            Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
+            Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
             if (err1 == err2) return err1;
             if (err1 == e.sym && err2 == e.sym2) return m2;
             if (err1 instanceof AmbiguityError &&
@@ -1059,13 +1156,83 @@
         }
     }
     //where
-    private boolean signatureMoreSpecific(Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
+    private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
+        Symbol m12 = adjustVarargs(m1, m2, useVarargs);
+        Symbol m22 = adjustVarargs(m2, m1, useVarargs);
+        Type mtype1 = types.memberType(site, m12);
+        Type mtype2 = types.memberType(site, m22);
+
+        //check if invocation is more specific
+        if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
+            return true;
+        }
+
+        //perform structural check
+
+        List<Type> formals1 = mtype1.getParameterTypes();
+        Type lastFormal1 = formals1.last();
+        List<Type> formals2 = mtype2.getParameterTypes();
+        Type lastFormal2 = formals2.last();
+        ListBuffer<Type> newFormals = ListBuffer.lb();
+
+        boolean hasStructuralPoly = false;
+        for (Type actual : actuals) {
+            //perform formal argument adaptation in case actuals > formals (varargs)
+            Type f1 = formals1.isEmpty() ?
+                    lastFormal1 : formals1.head;
+            Type f2 = formals2.isEmpty() ?
+                    lastFormal2 : formals2.head;
+
+            //is this a structural actual argument?
+            boolean isStructuralPoly = actual.tag == DEFERRED &&
+                    (((DeferredType)actual).tree.hasTag(LAMBDA) ||
+                    ((DeferredType)actual).tree.hasTag(REFERENCE));
+
+            Type newFormal = f1;
+
+            if (isStructuralPoly) {
+                //for structural arguments only - check that corresponding formals
+                //are related - if so replace formal with <null>
+                hasStructuralPoly = true;
+                DeferredType dt = (DeferredType)actual;
+                Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt);
+                Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt);
+                if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) {
+                    //not structural subtypes - simply fail
+                    return false;
+                } else {
+                    newFormal = syms.botType;
+                }
+            }
+
+            newFormals.append(newFormal);
+            if (newFormals.length() > mtype2.getParameterTypes().length()) {
+                //expand m2's type so as to fit the new formal arity (varargs)
+                m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
+            }
+
+            formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
+            formals2 = formals2.isEmpty() ? formals2 : formals2.tail;
+        }
+
+        if (!hasStructuralPoly) {
+            //if no structural actual was found, we're done
+            return false;
+        }
+        //perform additional adaptation if actuals < formals (varargs)
+        for (Type t : formals1) {
+            newFormals.append(t);
+        }
+        //check if invocation (with tweaked args) is more specific
+        return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs);
+    }
+    //where
+    private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
         noteWarner.clear();
-        Type mtype1 = types.memberType(site, adjustVarargs(m1, m2, useVarargs));
-        Type mtype2 = instantiate(env, site, adjustVarargs(m2, m1, useVarargs), null,
-                types.lowerBoundArgtypes(mtype1), null,
+        Type mst = instantiate(env, site, m2, null,
+                types.lowerBounds(argtypes1), null,
                 allowBoxing, false, noteWarner);
-        return mtype2 != null &&
+        return mst != null &&
                 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
     }
     //where
@@ -1104,6 +1271,32 @@
         }
     }
     //where
+    boolean isStructuralSubtype(Type s, Type t) {
+
+        Type ret_s = types.findDescriptorType(s).getReturnType();
+        Type ret_t = types.findDescriptorType(t).getReturnType();
+
+        //covariant most specific check for function descriptor return type
+        if (!types.isSubtype(ret_s, ret_t)) {
+            return false;
+        }
+
+        List<Type> args_s = types.findDescriptorType(s).getParameterTypes();
+        List<Type> args_t = types.findDescriptorType(t).getParameterTypes();
+
+        //arity must be identical
+        if (args_s.length() != args_t.length()) {
+            return false;
+        }
+
+        //invariant most specific check for function descriptor parameter types
+        if (!types.isSameTypes(args_t, args_s)) {
+            return false;
+        }
+
+        return true;
+    }
+    //where
     Type mostSpecificReturnType(Type mt1, Type mt2) {
         Type rt1 = mt1.getReturnType();
         Type rt2 = mt2.getReturnType();
@@ -1160,12 +1353,10 @@
                           argtypes,
                           typeargtypes,
                           site.tsym.type,
-                          true,
                           bestSoFar,
                           allowBoxing,
                           useVarargs,
-                          operator,
-                          new HashSet<TypeSymbol>());
+                          operator);
         reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar);
         return bestSoFar;
     }
@@ -1176,56 +1367,134 @@
                               List<Type> argtypes,
                               List<Type> typeargtypes,
                               Type intype,
-                              boolean abstractok,
                               Symbol bestSoFar,
                               boolean allowBoxing,
                               boolean useVarargs,
-                              boolean operator,
-                              Set<TypeSymbol> seen) {
-        for (Type ct = intype; ct.tag == CLASS || ct.tag == TYPEVAR; ct = types.supertype(ct)) {
-            while (ct.tag == TYPEVAR)
-                ct = ct.getUpperBound();
-            ClassSymbol c = (ClassSymbol)ct.tsym;
-            if (!seen.add(c)) return bestSoFar;
-            if ((c.flags() & (ABSTRACT | INTERFACE | ENUM)) == 0)
-                abstractok = false;
-            for (Scope.Entry e = c.members().lookup(name);
-                 e.scope != null;
-                 e = e.next()) {
-                //- System.out.println(" e " + e.sym);
-                if (e.sym.kind == MTH &&
-                    (e.sym.flags_field & SYNTHETIC) == 0) {
-                    bestSoFar = selectBest(env, site, argtypes, typeargtypes,
-                                           e.sym, bestSoFar,
-                                           allowBoxing,
-                                           useVarargs,
-                                           operator);
+                              boolean operator) {
+        boolean abstractOk = true;
+        List<Type> itypes = List.nil();
+        for (TypeSymbol s : superclasses(intype)) {
+            bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
+                    s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
+            //We should not look for abstract methods if receiver is a concrete class
+            //(as concrete classes are expected to implement all abstracts coming
+            //from superinterfaces)
+            abstractOk &= (s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0;
+            if (abstractOk) {
+                for (Type itype : types.interfaces(s.type)) {
+                    itypes = types.union(types.closure(itype), itypes);
                 }
             }
-            if (name == names.init)
-                break;
-            //- System.out.println(" - " + bestSoFar);
-            if (abstractok) {
-                Symbol concrete = methodNotFound;
-                if ((bestSoFar.flags() & ABSTRACT) == 0)
-                    concrete = bestSoFar;
-                for (List<Type> l = types.interfaces(c.type);
-                     l.nonEmpty();
-                     l = l.tail) {
-                    bestSoFar = findMethod(env, site, name, argtypes,
-                                           typeargtypes,
-                                           l.head, abstractok, bestSoFar,
-                                           allowBoxing, useVarargs, operator, seen);
-                }
-                if (concrete != bestSoFar &&
-                    concrete.kind < ERR  && bestSoFar.kind < ERR &&
-                    types.isSubSignature(concrete.type, bestSoFar.type))
-                    bestSoFar = concrete;
+            if (name == names.init) break;
+        }
+
+        Symbol concrete = bestSoFar.kind < ERR &&
+                (bestSoFar.flags() & ABSTRACT) == 0 ?
+                bestSoFar : methodNotFound;
+
+        if (name != names.init) {
+            //keep searching for abstract methods
+            for (Type itype : itypes) {
+                if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
+                bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
+                    itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
+                    if (concrete != bestSoFar &&
+                            concrete.kind < ERR  && bestSoFar.kind < ERR &&
+                            types.isSubSignature(concrete.type, bestSoFar.type)) {
+                        //this is an hack - as javac does not do full membership checks
+                        //most specific ends up comparing abstract methods that might have
+                        //been implemented by some concrete method in a subclass and,
+                        //because of raw override, it is possible for an abstract method
+                        //to be more specific than the concrete method - so we need
+                        //to explicitly call that out (see CR 6178365)
+                        bestSoFar = concrete;
+                    }
             }
         }
         return bestSoFar;
     }
 
+    /**
+     * Return an Iterable object to scan the superclasses of a given type.
+     * It's crucial that the scan is done lazily, as we don't want to accidentally
+     * access more supertypes than strictly needed (as this could trigger completion
+     * errors if some of the not-needed supertypes are missing/ill-formed).
+     */
+    Iterable<TypeSymbol> superclasses(final Type intype) {
+        return new Iterable<TypeSymbol>() {
+            public Iterator<TypeSymbol> iterator() {
+                return new Iterator<TypeSymbol>() {
+
+                    List<TypeSymbol> seen = List.nil();
+                    TypeSymbol currentSym = symbolFor(intype);
+                    TypeSymbol prevSym = null;
+
+                    public boolean hasNext() {
+                        if (currentSym == syms.noSymbol) {
+                            currentSym = symbolFor(types.supertype(prevSym.type));
+                        }
+                        return currentSym != null;
+                    }
+
+                    public TypeSymbol next() {
+                        prevSym = currentSym;
+                        currentSym = syms.noSymbol;
+                        Assert.check(prevSym != null || prevSym != syms.noSymbol);
+                        return prevSym;
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    TypeSymbol symbolFor(Type t) {
+                        if (t.tag != CLASS &&
+                                t.tag != TYPEVAR) {
+                            return null;
+                        }
+                        while (t.tag == TYPEVAR)
+                            t = t.getUpperBound();
+                        if (seen.contains(t.tsym)) {
+                            //degenerate case in which we have a circular
+                            //class hierarchy - because of ill-formed classfiles
+                            return null;
+                        }
+                        seen = seen.prepend(t.tsym);
+                        return t.tsym;
+                    }
+                };
+            }
+        };
+    }
+
+    /**
+     * Lookup a method with given name and argument types in a given scope
+     */
+    Symbol lookupMethod(Env<AttrContext> env,
+            Type site,
+            Name name,
+            List<Type> argtypes,
+            List<Type> typeargtypes,
+            Scope sc,
+            Symbol bestSoFar,
+            boolean allowBoxing,
+            boolean useVarargs,
+            boolean operator,
+            boolean abstractok) {
+        for (Symbol s : sc.getElementsByName(name, lookupFilter)) {
+            bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
+                    bestSoFar, allowBoxing, useVarargs, operator);
+        }
+        return bestSoFar;
+    }
+    //where
+        Filter<Symbol> lookupFilter = new Filter<Symbol>() {
+            public boolean accepts(Symbol s) {
+                return s.kind == MTH &&
+                        (s.flags() & SYNTHETIC) == 0;
+            }
+        };
+
     /** Find unqualified method matching given name, type and value arguments.
      *  @param env       The current environment.
      *  @param name      The method's name.
@@ -1521,14 +1790,41 @@
      *
      *  @param sym       The symbol that was found, or a ResolveError.
      *  @param pos       The position to use for error reporting.
+     *  @param location  The symbol the served as a context for this lookup
      *  @param site      The original type from where the selection took place.
      *  @param name      The symbol's name.
+     *  @param qualified Did we get here through a qualified expression resolution?
      *  @param argtypes  The invocation's value arguments,
      *                   if we looked for a method.
      *  @param typeargtypes  The invocation's type arguments,
      *                   if we looked for a method.
+     *  @param logResolveHelper helper class used to log resolve errors
      */
-    Symbol access(Symbol sym,
+    Symbol accessInternal(Symbol sym,
+                  DiagnosticPosition pos,
+                  Symbol location,
+                  Type site,
+                  Name name,
+                  boolean qualified,
+                  List<Type> argtypes,
+                  List<Type> typeargtypes,
+                  LogResolveHelper logResolveHelper) {
+        if (sym.kind >= AMBIGUOUS) {
+            ResolveError errSym = (ResolveError)sym;
+            sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
+            argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes);
+            if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) {
+                logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
+            }
+        }
+        return sym;
+    }
+
+    /**
+     * Variant of the generalized access routine, to be used for generating method
+     * resolution diagnostics
+     */
+    Symbol accessMethod(Symbol sym,
                   DiagnosticPosition pos,
                   Symbol location,
                   Type site,
@@ -1536,53 +1832,91 @@
                   boolean qualified,
                   List<Type> argtypes,
                   List<Type> typeargtypes) {
-        if (sym.kind >= AMBIGUOUS) {
-            ResolveError errSym = (ResolveError)sym;
-            if (!site.isErroneous() &&
-                !Type.isErroneous(argtypes) &&
-                (typeargtypes==null || !Type.isErroneous(typeargtypes)))
-                logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
-            sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
-        }
-        return sym;
+        return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper);
     }
 
-    /** Same as original access(), but without location.
+    /** Same as original accessMethod(), but without location.
      */
-    Symbol access(Symbol sym,
+    Symbol accessMethod(Symbol sym,
                   DiagnosticPosition pos,
                   Type site,
                   Name name,
                   boolean qualified,
                   List<Type> argtypes,
                   List<Type> typeargtypes) {
-        return access(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
+        return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
     }
 
-    /** Same as original access(), but without type arguments and arguments.
+    /**
+     * Variant of the generalized access routine, to be used for generating variable,
+     * type resolution diagnostics
      */
-    Symbol access(Symbol sym,
+    Symbol accessBase(Symbol sym,
                   DiagnosticPosition pos,
                   Symbol location,
                   Type site,
                   Name name,
                   boolean qualified) {
-        if (sym.kind >= AMBIGUOUS)
-            return access(sym, pos, location, site, name, qualified, List.<Type>nil(), null);
-        else
-            return sym;
+        return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper);
     }
 
-    /** Same as original access(), but without location, type arguments and arguments.
+    /** Same as original accessBase(), but without location.
      */
-    Symbol access(Symbol sym,
+    Symbol accessBase(Symbol sym,
                   DiagnosticPosition pos,
                   Type site,
                   Name name,
                   boolean qualified) {
-        return access(sym, pos, site.tsym, site, name, qualified);
+        return accessBase(sym, pos, site.tsym, site, name, qualified);
     }
 
+    interface LogResolveHelper {
+        boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes);
+        List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes);
+    }
+
+    LogResolveHelper basicLogResolveHelper = new LogResolveHelper() {
+        public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
+            return !site.isErroneous();
+        }
+        public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
+            return argtypes;
+        }
+    };
+
+    LogResolveHelper methodLogResolveHelper = new LogResolveHelper() {
+        public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) {
+            return !site.isErroneous() &&
+                        !Type.isErroneous(argtypes) &&
+                        (typeargtypes == null || !Type.isErroneous(typeargtypes));
+        }
+        public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
+            if (syms.operatorNames.contains(name)) {
+                return argtypes;
+            } else {
+                Symbol msym = errSym.kind == WRONG_MTH ?
+                        ((InapplicableSymbolError)errSym).errCandidate().sym : accessedSym;
+
+                List<Type> argtypes2 = Type.map(argtypes,
+                        deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, msym, currentResolutionContext.firstErroneousResolutionPhase()));
+
+                if (msym != accessedSym) {
+                    //fixup deferred type caches - this 'hack' is required because the symbol
+                    //returned by InapplicableSymbolError.access() will hide the candidate
+                    //method symbol that can be used for lookups in the speculative cache,
+                    //causing problems in Attr.checkId()
+                    for (Type t : argtypes) {
+                        if (t.tag == DEFERRED) {
+                            DeferredType dt = (DeferredType)t;
+                            dt.speculativeCache.dupAllTo(msym, accessedSym);
+                        }
+                    }
+                }
+                return argtypes2;
+            }
+        }
+    };
+
     /** Check that sym is not an abstract method.
      */
     void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
@@ -1641,7 +1975,7 @@
      */
     Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
                         Name name, int kind) {
-        return access(
+        return accessBase(
             findIdent(env, name, kind),
             pos, env.enclClass.sym.type, name, false);
     }
@@ -1666,19 +2000,19 @@
             while (steps.nonEmpty() &&
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= ERRONEOUS) {
-                currentResolutionContext.step = steps.head;
+                currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
                 sym = findFun(env, name, argtypes, typeargtypes,
                         steps.head.isBoxingRequired,
-                        env.info.varArgs = steps.head.isVarargsRequired);
+                        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),
+                sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
                         pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired;
+                env.info.pendingResolutionPhase = errPhase;
             }
             return sym;
         }
@@ -1718,10 +2052,10 @@
             while (steps.nonEmpty() &&
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= ERRONEOUS) {
-                currentResolutionContext.step = steps.head;
+                currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
                 sym = findMethod(env, site, name, argtypes, typeargtypes,
                         steps.head.isBoxingRequired(),
-                        env.info.varArgs = steps.head.isVarargsRequired(), false);
+                        steps.head.isVarargsRequired(), false);
                 currentResolutionContext.resolutionCache.put(steps.head, sym);
                 steps = steps.tail;
             }
@@ -1729,13 +2063,13 @@
                 //if nothing is found return the 'first' error
                 MethodResolutionPhase errPhase =
                         currentResolutionContext.firstErroneousResolutionPhase();
-                sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+                sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
                         pos, location, site, name, true, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired;
+                env.info.pendingResolutionPhase = errPhase;
             } else if (allowMethodHandles) {
                 MethodSymbol msym = (MethodSymbol)sym;
                 if (msym.isSignaturePolymorphic(types)) {
-                    env.info.varArgs = false;
+                    env.info.pendingResolutionPhase = BASIC;
                     return findPolymorphicSignatureInstance(env, sym, argtypes);
                 }
             }
@@ -1757,7 +2091,7 @@
                                             Symbol spMethod,
                                             List<Type> argtypes) {
         Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
-                (MethodSymbol)spMethod, argtypes);
+                (MethodSymbol)spMethod, currentResolutionContext, argtypes);
         for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) {
             if (types.isSameType(mtype, sym.type)) {
                return sym;
@@ -1825,18 +2159,18 @@
             while (steps.nonEmpty() &&
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= ERRONEOUS) {
-                currentResolutionContext.step = steps.head;
+                currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
                 sym = findConstructor(pos, env, site, argtypes, typeargtypes,
                         steps.head.isBoxingRequired(),
-                        env.info.varArgs = steps.head.isVarargsRequired());
+                        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),
+                sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase),
                         pos, site, names.init, true, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired();
+                env.info.pendingResolutionPhase = errPhase;
             }
             return sym;
         }
@@ -1868,18 +2202,20 @@
             while (steps.nonEmpty() &&
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= ERRONEOUS) {
-                currentResolutionContext.step = steps.head;
+                currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
                 sym = findDiamond(env, site, argtypes, typeargtypes,
                         steps.head.isBoxingRequired(),
-                        env.info.varArgs = steps.head.isVarargsRequired());
+                        steps.head.isVarargsRequired());
                 currentResolutionContext.resolutionCache.put(steps.head, sym);
                 steps = steps.tail;
             }
             if (sym.kind >= AMBIGUOUS) {
-                final JCDiagnostic details = sym.kind == WRONG_MTH ?
-                                currentResolutionContext.candidates.head.details :
+                Symbol errSym =
+                        currentResolutionContext.resolutionCache.get(currentResolutionContext.firstErroneousResolutionPhase());
+                final JCDiagnostic details = errSym.kind == WRONG_MTH ?
+                                ((InapplicableSymbolError)errSym).errCandidate().details :
                                 null;
-                Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
+                errSym = new InapplicableSymbolError(errSym.kind, "diamondError", currentResolutionContext) {
                     @Override
                     JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
                             Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
@@ -1891,8 +2227,8 @@
                     }
                 };
                 MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
-                sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
-                env.info.varArgs = errPhase.isVarargsRequired();
+                sym = accessMethod(errSym, pos, site, names.init, true, argtypes, typeargtypes);
+                env.info.pendingResolutionPhase = errPhase;
             }
             return sym;
         }
@@ -1919,16 +2255,23 @@
         for (Scope.Entry e = site.tsym.members().lookup(names.init);
              e.scope != null;
              e = e.next()) {
+            final Symbol sym = e.sym;
             //- System.out.println(" e " + e.sym);
-            if (e.sym.kind == MTH &&
-                (e.sym.flags_field & SYNTHETIC) == 0) {
+            if (sym.kind == MTH &&
+                (sym.flags_field & SYNTHETIC) == 0) {
                     List<Type> oldParams = e.sym.type.tag == FORALL ?
-                            ((ForAll)e.sym.type).tvars :
+                            ((ForAll)sym.type).tvars :
                             List.<Type>nil();
                     Type constrType = new ForAll(site.tsym.type.getTypeArguments().appendList(oldParams),
-                            types.createMethodTypeWithReturn(e.sym.type.asMethodType(), site));
+                            types.createMethodTypeWithReturn(sym.type.asMethodType(), site));
+                    MethodSymbol newConstr = new MethodSymbol(sym.flags(), names.init, constrType, site.tsym) {
+                        @Override
+                        public Symbol baseSymbol() {
+                            return sym;
+                        }
+                    };
                     bestSoFar = selectBest(env, site, argtypes, typeargtypes,
-                            new MethodSymbol(e.sym.flags(), names.init, constrType, site.tsym),
+                            newConstr,
                             bestSoFar,
                             allowBoxing,
                             useVarargs,
@@ -1938,6 +2281,335 @@
         return bestSoFar;
     }
 
+    /**
+     * Resolution of member references is typically done as a single
+     * overload resolution step, where the argument types A are inferred from
+     * the target functional descriptor.
+     *
+     * If the member reference is a method reference with a type qualifier,
+     * a two-step lookup process is performed. The first step uses the
+     * expected argument list A, while the second step discards the first
+     * type from A (which is treated as a receiver type).
+     *
+     * There are two cases in which inference is performed: (i) if the member
+     * reference is a constructor reference and the qualifier type is raw - in
+     * which case diamond inference is used to infer a parameterization for the
+     * type qualifier; (ii) if the member reference is an unbound reference
+     * where the type qualifier is raw - in that case, during the unbound lookup
+     * the receiver argument type is used to infer an instantiation for the raw
+     * qualifier type.
+     *
+     * When a multi-step resolution process is exploited, it is an error
+     * if two candidates are found (ambiguity).
+     *
+     * This routine returns a pair (T,S), where S is the member reference symbol,
+     * and T is the type of the class in which S is defined. This is necessary as
+     * the type T might be dynamically inferred (i.e. if constructor reference
+     * has a raw qualifier).
+     */
+    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
+                                  Env<AttrContext> env,
+                                  JCMemberReference referenceTree,
+                                  Type site,
+                                  Name name, List<Type> argtypes,
+                                  List<Type> typeargtypes,
+                                  boolean boxingAllowed) {
+        //step 1 - bound lookup
+        ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
+                new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, boxingAllowed) :
+                new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
+        Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
+        Symbol boundSym = findMemberReference(boundEnv, boundLookupHelper);
+
+        //step 2 - unbound lookup
+        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
+        Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
+        Symbol unboundSym = findMemberReference(unboundEnv, unboundLookupHelper);
+
+        //merge results
+        Pair<Symbol, ReferenceLookupHelper> res;
+        if (unboundSym.kind != MTH) {
+            res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
+            env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+        } else if (boundSym.kind == MTH) {
+            res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
+            env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+        } else {
+            res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
+            env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
+        }
+
+        return res;
+    }
+
+    /**
+     * Helper for defining custom method-like lookup logic; a lookup helper
+     * provides hooks for (i) the actual lookup logic and (ii) accessing the
+     * lookup result (this step might result in compiler diagnostics to be generated)
+     */
+    abstract class LookupHelper {
+
+        /** name of the symbol to lookup */
+        Name name;
+
+        /** location in which the lookup takes place */
+        Type site;
+
+        /** actual types used during the lookup */
+        List<Type> argtypes;
+
+        /** type arguments used during the lookup */
+        List<Type> typeargtypes;
+
+        LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
+            this.name = name;
+            this.site = site;
+            this.argtypes = argtypes;
+            this.typeargtypes = typeargtypes;
+        }
+
+        /**
+         * Search for a symbol under a given overload resolution phase - this method
+         * is usually called several times, once per each overload resolution phase
+         */
+        abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
+
+        /**
+         * Validate the result of the lookup
+         */
+        abstract Symbol access(Env<AttrContext> env, Symbol symbol);
+    }
+
+    /**
+     * Helper class for member reference lookup. A reference lookup helper
+     * defines the basic logic for member reference lookup; a method gives
+     * access to an 'unbound' helper used to perform an unbound member
+     * reference lookup.
+     */
+    abstract class ReferenceLookupHelper extends LookupHelper {
+
+        /** The member reference tree */
+        JCMemberReference referenceTree;
+
+        /** Max overload resolution phase handled by this helper */
+        MethodResolutionPhase maxPhase;
+
+        ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(name, site, argtypes, typeargtypes);
+            this.referenceTree = referenceTree;
+            this.maxPhase = boxingAllowed ? VARARITY : BASIC;
+        }
+
+        /**
+         * Returns an unbound version of this lookup helper. By default, this
+         * method returns an dummy lookup helper.
+         */
+        ReferenceLookupHelper unboundLookup() {
+            //dummy loopkup helper that always return 'methodNotFound'
+            return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase.isBoxingRequired()) {
+                @Override
+                ReferenceLookupHelper unboundLookup() {
+                    return this;
+                }
+                @Override
+                Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+                    return methodNotFound;
+                }
+                @Override
+                ReferenceKind referenceKind(Symbol sym) {
+                    Assert.error();
+                    return null;
+                }
+            };
+        }
+
+        /**
+         * Get the kind of the member reference
+         */
+        abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
+
+        @Override
+        Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return (env.info.pendingResolutionPhase.ordinal() > maxPhase.ordinal()) ?
+                    methodNotFound : lookupReference(env, phase);
+        }
+
+        abstract Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase);
+
+        Symbol access(Env<AttrContext> env, Symbol sym) {
+            if (sym.kind >= AMBIGUOUS) {
+                MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+                if (errPhase.ordinal() > maxPhase.ordinal()) {
+                    errPhase = maxPhase;
+                }
+                env.info.pendingResolutionPhase = errPhase;
+                sym = currentResolutionContext.resolutionCache.get(errPhase);
+            }
+            return sym;
+        }
+    }
+
+    /**
+     * Helper class for method reference lookup. The lookup logic is based
+     * upon Resolve.findMethod; in certain cases, this helper class has a
+     * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
+     * In such cases, non-static lookup results are thrown away.
+     */
+    class MethodReferenceLookupHelper extends ReferenceLookupHelper {
+
+        MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
+        }
+
+        protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return findMethod(env, site, name, argtypes, typeargtypes,
+                    phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+        }
+
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
+                        sym.kind != MTH ||
+                        sym.isStatic() ? sym : new StaticError(sym);
+        }
+
+        @Override
+        final Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return adjustLookupResult(env, lookupReferenceInternal(env, phase));
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
+                    argtypes.nonEmpty() &&
+                    types.isSubtypeUnchecked(argtypes.head, site)) {
+                return new UnboundMethodReferenceLookupHelper(referenceTree, name,
+                        site, argtypes, typeargtypes, maxPhase.isBoxingRequired());
+            } else {
+                return super.unboundLookup();
+            }
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            if (sym.isStatic()) {
+                return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
+                        ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
+            } else {
+                Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
+                return selName != null && selName == names._super ?
+                        ReferenceKind.SUPER :
+                        ReferenceKind.BOUND;
+            }
+        }
+    }
+
+    /**
+     * Helper class for unbound method reference lookup. Essentially the same
+     * as the basic method reference lookup helper; main difference is that static
+     * lookup results are thrown away. If qualifier type is raw, an attempt to
+     * infer a parameterized type is made using the first actual argument (that
+     * would otherwise be ignored during the lookup).
+     */
+    class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
+
+        UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, name,
+                    site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site,
+                    argtypes.tail, typeargtypes, boxingAllowed);
+        }
+
+        @Override
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            return this;
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return ReferenceKind.UNBOUND;
+        }
+    }
+
+    /**
+     * Helper class for constructor reference lookup. The lookup logic is based
+     * upon either Resolve.findMethod or Resolve.findDiamond - depending on
+     * whether the constructor reference needs diamond inference (this is the case
+     * if the qualifier type is raw). A special erroneous symbol is returned
+     * if the lookup returns the constructor of an inner class and there's no
+     * enclosing instance in scope.
+     */
+    class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
+
+        boolean needsInference;
+
+        ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
+                List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, names.init, site, argtypes, typeargtypes, boxingAllowed);
+            if (site.isRaw()) {
+                this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym);
+                needsInference = true;
+            }
+        }
+
+        @Override
+        protected Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+            Symbol sym = needsInference ?
+                findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
+                findMethod(env, site, name, argtypes, typeargtypes,
+                        phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+            return sym.kind != MTH ||
+                          site.getEnclosingType().tag == NONE ||
+                          hasEnclosingInstance(env, site) ?
+                          sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
+                    @Override
+                    JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+                       return diags.create(dkind, log.currentSource(), pos,
+                            "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
+                    }
+                };
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return site.getEnclosingType().tag == NONE ?
+                    ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
+        }
+    }
+
+    /**
+     * Resolution step for member reference. This generalizes a standard
+     * method/constructor lookup - on each overload resolution step, a
+     * lookup helper class is used to perform the reference lookup; at the end
+     * of the lookup, the helper is used to validate the results.
+     */
+    Symbol findMemberReference(Env<AttrContext> env, LookupHelper lookupHelper) {
+        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 = env.info.pendingResolutionPhase = steps.head;
+                sym = lookupHelper.lookup(env, steps.head);
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            return lookupHelper.access(env, sym);
+        }
+        finally {
+            currentResolutionContext = prevResolutionContext;
+        }
+    }
+
     /** Resolve constructor.
      *  @param pos       The position to use for error reporting.
      *  @param env       The environment current at the constructor invocation.
@@ -2013,7 +2685,7 @@
             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,
+            return accessMethod(sym, pos, env.enclClass.sym.type, name,
                           false, argtypes, null);
         }
         finally {
@@ -2065,7 +2737,7 @@
                 Symbol sym = env1.info.scope.lookup(name).sym;
                 if (sym != null) {
                     if (staticOnly) sym = new StaticError(sym);
-                    return access(sym, pos, env.enclClass.sym.type,
+                    return accessBase(sym, pos, env.enclClass.sym.type,
                                   name, true);
                 }
             }
@@ -2087,6 +2759,23 @@
                                  Env<AttrContext> env,
                                  Symbol member,
                                  boolean isSuperCall) {
+        Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall);
+        if (sym == null) {
+            log.error(pos, "encl.class.required", member);
+            return syms.errSymbol;
+        } else {
+            return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true);
+        }
+    }
+
+    boolean hasEnclosingInstance(Env<AttrContext> env, Type type) {
+        Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
+        return encl != null && encl.kind < ERRONEOUS;
+    }
+
+    private Symbol resolveSelfContainingInternal(Env<AttrContext> env,
+                                 Symbol member,
+                                 boolean isSuperCall) {
         Name name = names._this;
         Env<AttrContext> env1 = isSuperCall ? env.outer : env;
         boolean staticOnly = false;
@@ -2097,8 +2786,7 @@
                     Symbol sym = env1.info.scope.lookup(name).sym;
                     if (sym != null) {
                         if (staticOnly) sym = new StaticError(sym);
-                        return access(sym, pos, env.enclClass.sym.type,
-                                      name, true);
+                        return sym;
                     }
                 }
                 if ((env1.enclClass.sym.flags() & STATIC) != 0)
@@ -2106,8 +2794,7 @@
                 env1 = env1.outer;
             }
         }
-        log.error(pos, "encl.class.required", member);
-        return syms.errSymbol;
+        return null;
     }
 
     /**
@@ -2155,7 +2842,19 @@
     private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args");
 
     public Object methodArguments(List<Type> argtypes) {
-        return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes;
+        if (argtypes == null || argtypes.isEmpty()) {
+            return noArgs;
+        } else {
+            ListBuffer<Object> diagArgs = ListBuffer.lb();
+            for (Type t : argtypes) {
+                if (t.tag == DEFERRED) {
+                    diagArgs.append(((DeferredAttr.DeferredType)t).tree);
+                } else {
+                    diagArgs.append(t);
+                }
+            }
+            return diagArgs;
+        }
     }
 
     /**
@@ -2163,7 +2862,7 @@
      * represent a different kinds of resolution error - as such they must
      * specify how they map into concrete compiler diagnostics.
      */
-    private abstract class ResolveError extends Symbol {
+    abstract class ResolveError extends Symbol {
 
         /** The name of the kind of error, for debugging only. */
         final String debugName;
@@ -2220,17 +2919,6 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes);
-
-        /**
-         * A name designates an operator if it consists
-         * of a non-empty sequence of operator symbols {@literal +-~!/*%&|^<>= }
-         */
-        boolean isOperator(Name name) {
-            int i = 0;
-            while (i < name.getByteLength() &&
-                   "+-~!*/%&|^<>=".indexOf(name.getByteAt(i)) >= 0) i++;
-            return i > 0 && i == name.getByteLength();
-        }
     }
 
     /**
@@ -2291,7 +2979,7 @@
             if (name == names.error)
                 return null;
 
-            if (isOperator(name)) {
+            if (syms.operatorNames.contains(name)) {
                 boolean isUnaryOp = argtypes.size() == 1;
                 String key = argtypes.size() == 1 ?
                     "operator.cant.be.applied" :
@@ -2313,8 +3001,7 @@
                 hasLocation = !location.name.equals(names._this) &&
                         !location.name.equals(names._super);
             }
-            boolean isConstructor = kind == ABSENT_MTH &&
-                    name == names.table.names.init;
+            boolean isConstructor = kind == ABSENT_MTH && name == names.init;
             KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
             Name idname = isConstructor ? site.tsym.name : name;
             String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
@@ -2365,12 +3052,15 @@
      */
     class InapplicableSymbolError extends ResolveError {
 
-        InapplicableSymbolError() {
-            super(WRONG_MTH, "inapplicable symbol error");
+        protected MethodResolutionContext resolveContext;
+
+        InapplicableSymbolError(MethodResolutionContext context) {
+            this(WRONG_MTH, "inapplicable symbol error", context);
         }
 
-        protected InapplicableSymbolError(int kind, String debugName) {
+        protected InapplicableSymbolError(int kind, String debugName, MethodResolutionContext context) {
             super(kind, debugName);
+            this.resolveContext = context;
         }
 
         @Override
@@ -2394,7 +3084,7 @@
             if (name == names.error)
                 return null;
 
-            if (isOperator(name)) {
+            if (syms.operatorNames.contains(name)) {
                 boolean isUnaryOp = argtypes.size() == 1;
                 String key = argtypes.size() == 1 ?
                     "operator.cant.be.applied" :
@@ -2408,7 +3098,7 @@
                 Candidate c = errCandidate();
                 Symbol ws = c.sym.asMemberOf(site, types);
                 return diags.create(dkind, log.currentSource(), pos,
-                          "cant.apply.symbol" + (c.details != null ? ".1" : ""),
+                          "cant.apply.symbol",
                           kindName(ws),
                           ws.name == names.init ? ws.owner.name : ws.name,
                           methodArguments(ws.type.getParameterTypes()),
@@ -2425,13 +3115,13 @@
         }
 
         protected boolean shouldReport(Candidate c) {
+            MethodResolutionPhase errPhase = resolveContext.firstErroneousResolutionPhase();
             return !c.isApplicable() &&
-                    (((c.sym.flags() & VARARGS) != 0 && c.step == VARARITY) ||
-                      (c.sym.flags() & VARARGS) == 0 && c.step == (boxingEnabled ? BOX : BASIC));
+                    c.step == errPhase;
         }
 
         private Candidate errCandidate() {
-            for (Candidate c : currentResolutionContext.candidates) {
+            for (Candidate c : resolveContext.candidates) {
                 if (shouldReport(c)) {
                     return c;
                 }
@@ -2448,8 +3138,8 @@
      */
     class InapplicableSymbolsError extends InapplicableSymbolError {
 
-        InapplicableSymbolsError() {
-            super(WRONG_MTHS, "inapplicable symbols");
+        InapplicableSymbolsError(MethodResolutionContext context) {
+            super(WRONG_MTHS, "inapplicable symbols", context);
         }
 
         @Override
@@ -2460,7 +3150,7 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes) {
-            if (currentResolutionContext.candidates.nonEmpty()) {
+            if (!resolveContext.candidates.isEmpty()) {
                 JCDiagnostic err = diags.create(dkind,
                         log.currentSource(),
                         pos,
@@ -2478,7 +3168,7 @@
         //where
         List<JCDiagnostic> candidateDetails(Type site) {
             List<JCDiagnostic> details = List.nil();
-            for (Candidate c : currentResolutionContext.candidates) {
+            for (Candidate c : resolveContext.candidates) {
                 if (!shouldReport(c)) continue;
                 JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
                         Kinds.kindName(c.sym),
@@ -2491,7 +3181,7 @@
         }
 
         private Name getName() {
-            Symbol sym = currentResolutionContext.candidates.head.sym;
+            Symbol sym = resolveContext.candidates.head.sym;
             return sym.name == names.init ?
                 sym.owner.name :
                 sym.name;
@@ -2672,9 +3362,10 @@
         private Map<MethodResolutionPhase, Symbol> resolutionCache =
             new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class);
 
-        private MethodResolutionPhase step = null;
+        MethodResolutionPhase step = null;
 
         private boolean internalResolution = false;
+        private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
 
         private MethodResolutionPhase firstErroneousResolutionPhase() {
             MethodResolutionPhase bestSoFar = BASIC;
@@ -2684,6 +3375,7 @@
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= WRONG_MTHS) {
                 sym = resolutionCache.get(steps.head);
+                if (sym.kind == ABSENT_MTH) break; //ignore spurious empty entries
                 bestSoFar = steps.head;
                 steps = steps.tail;
             }
@@ -2692,8 +3384,7 @@
 
         void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
             Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
-            if (!candidates.contains(c))
-                candidates = candidates.append(c);
+            candidates = candidates.append(c);
         }
 
         void addApplicableCandidate(Symbol sym, Type mtype) {
@@ -2701,6 +3392,16 @@
             candidates = candidates.append(c);
         }
 
+        Candidate getCandidate(Symbol sym, MethodResolutionPhase phase) {
+            for (Candidate c : currentResolutionContext.candidates) {
+                if (c.step == phase &&
+                        c.sym.baseSymbol() == sym.baseSymbol()) {
+                    return c;
+                }
+            }
+            return null;
+        }
+
         /**
          * This class represents an overload resolution candidate. There are two
          * kinds of candidates: applicable methods and inapplicable methods;
@@ -2728,9 +3429,9 @@
                     Symbol s1 = this.sym;
                     Symbol s2 = ((Candidate)o).sym;
                     if  ((s1 != s2 &&
-                        (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
-                        (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
-                        ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
+                            (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
+                            (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
+                            ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
                         return true;
                 }
                 return false;
@@ -2740,6 +3441,14 @@
                 return mtype != null;
             }
         }
+
+        DeferredAttr.AttrMode attrMode() {
+            return attrMode;
+        }
+
+        boolean internal() {
+            return internalResolution;
+        }
     }
 
     MethodResolutionContext currentResolutionContext = null;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Oct 11 17:00:54 2012 -0700
@@ -627,6 +627,16 @@
         result = tree;
     }
 
+    @Override
+    public void visitLambda(JCLambda tree) {
+        Assert.error("Translation of lambda expression not supported yet");
+    }
+
+    @Override
+    public void visitReference(JCMemberReference tree) {
+        Assert.error("Translation of method reference not supported yet");
+    }
+
     public void visitParens(JCParens tree) {
         tree.expr = translate(tree.expr, pt);
         tree.type = erasure(tree.type);
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java	Thu Oct 11 17:00:54 2012 -0700
@@ -733,11 +733,7 @@
                 urls[count++] = url;
             }
         }
-        if (urls.length != count) {
-            URL[] tmp = new URL[count];
-            System.arraycopy(urls, 0, tmp, 0, count);
-            urls = tmp;
-        }
+        urls = Arrays.copyOf(urls, count);
         return urls;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Thu Oct 11 17:00:54 2012 -0700
@@ -84,6 +84,16 @@
     public final static int CONSTANT_MethodType = 16;
     public final static int CONSTANT_InvokeDynamic = 18;
 
+    public final static int REF_getField = 1;
+    public final static int REF_getStatic = 2;
+    public final static int REF_putField = 3;
+    public final static int REF_putStatic = 4;
+    public final static int REF_invokeVirtual = 5;
+    public final static int REF_invokeStatic = 6;
+    public final static int REF_invokeSpecial = 7;
+    public final static int REF_newInvokeSpecial = 8;
+    public final static int REF_invokeInterface = 9;
+
     public final static int MAX_PARAMETERS = 0xff;
     public final static int MAX_DIMENSIONS = 0xff;
     public final static int MAX_CODE = 0xffff;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -26,6 +26,8 @@
 package com.sun.tools.javac.jvm;
 
 import java.io.*;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Set;
 import java.util.HashSet;
 
@@ -137,6 +139,11 @@
      */
     ListBuffer<ClassSymbol> innerClassesQueue;
 
+    /** The bootstrap methods to be written in the corresponding class attribute
+     *  (one for each invokedynamic)
+     */
+    Map<MethodSymbol, Pool.MethodHandle> bootstrapMethods;
+
     /** The log to use for verbose output.
      */
     private final Log log;
@@ -477,11 +484,27 @@
 
             if (value instanceof MethodSymbol) {
                 MethodSymbol m = (MethodSymbol)value;
-                poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
-                          ? CONSTANT_InterfaceMethodref
-                          : CONSTANT_Methodref);
-                poolbuf.appendChar(pool.put(m.owner));
-                poolbuf.appendChar(pool.put(nameType(m)));
+                if (!m.isDynamic()) {
+                    poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
+                              ? CONSTANT_InterfaceMethodref
+                              : CONSTANT_Methodref);
+                    poolbuf.appendChar(pool.put(m.owner));
+                    poolbuf.appendChar(pool.put(nameType(m)));
+                } else {
+                    //invokedynamic
+                    DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
+                    Pool.MethodHandle handle = new Pool.MethodHandle(dynSym.bsmKind, dynSym.bsm);
+                    bootstrapMethods.put(dynSym, handle);
+                    //init cp entries
+                    pool.put(names.BootstrapMethods);
+                    pool.put(handle);
+                    for (Object staticArg : dynSym.staticArgs) {
+                        pool.put(staticArg);
+                    }
+                    poolbuf.appendByte(CONSTANT_InvokeDynamic);
+                    poolbuf.appendChar(bootstrapMethods.size() - 1);
+                    poolbuf.appendChar(pool.put(nameType(dynSym)));
+                }
             } else if (value instanceof VarSymbol) {
                 VarSymbol v = (VarSymbol)value;
                 poolbuf.appendByte(CONSTANT_Fieldref);
@@ -526,11 +549,20 @@
             } else if (value instanceof String) {
                 poolbuf.appendByte(CONSTANT_String);
                 poolbuf.appendChar(pool.put(names.fromString((String)value)));
+            } else if (value instanceof MethodType) {
+                MethodType mtype = (MethodType)value;
+                poolbuf.appendByte(CONSTANT_MethodType);
+                poolbuf.appendChar(pool.put(typeSig(mtype)));
             } else if (value instanceof Type) {
                 Type type = (Type)value;
                 if (type.tag == CLASS) enterInner((ClassSymbol)type.tsym);
                 poolbuf.appendByte(CONSTANT_Class);
                 poolbuf.appendChar(pool.put(xClassName(type)));
+            } else if (value instanceof Pool.MethodHandle) {
+                Pool.MethodHandle ref = (Pool.MethodHandle)value;
+                poolbuf.appendByte(CONSTANT_MethodHandle);
+                poolbuf.appendByte(ref.refKind);
+                poolbuf.appendChar(pool.put(ref.refSym));
             } else {
                 Assert.error("writePool " + value);
             }
@@ -914,6 +946,25 @@
         endAttr(alenIdx);
     }
 
+    /** Write "bootstrapMethods" attribute.
+     */
+    void writeBootstrapMethods() {
+        int alenIdx = writeAttr(names.BootstrapMethods);
+        databuf.appendChar(bootstrapMethods.size());
+        for (Map.Entry<MethodSymbol, Pool.MethodHandle> entry : bootstrapMethods.entrySet()) {
+            DynamicMethodSymbol dsym = (DynamicMethodSymbol)entry.getKey();
+            //write BSM handle
+            databuf.appendChar(pool.get(entry.getValue()));
+            //write static args length
+            databuf.appendChar(dsym.staticArgs.length);
+            //write static args array
+            for (Object o : dsym.staticArgs) {
+                databuf.appendChar(pool.get(o));
+            }
+        }
+        endAttr(alenIdx);
+    }
+
     /** Write field symbol, entering all references into constant pool.
      */
     void writeField(VarSymbol v) {
@@ -1483,6 +1534,7 @@
         pool = c.pool;
         innerClasses = null;
         innerClassesQueue = null;
+        bootstrapMethods = new LinkedHashMap<MethodSymbol, Pool.MethodHandle>();
 
         Type supertype = types.supertype(c.type);
         List<Type> interfaces = types.interfaces(c.type);
@@ -1589,6 +1641,12 @@
             writeInnerClasses();
             acount++;
         }
+
+        if (!bootstrapMethods.isEmpty()) {
+            writeBootstrapMethods();
+            acount++;
+        }
+
         endAttrs(acountIdx, acount);
 
         poolbuf.appendBytes(databuf.elems, 0, databuf.length);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Thu Oct 11 17:00:54 2012 -0700
@@ -314,11 +314,7 @@
      */
     private  void emit1(int od) {
         if (!alive) return;
-        if (cp == code.length) {
-            byte[] newcode = new byte[cp * 2];
-            System.arraycopy(code, 0, newcode, 0, cp);
-            code = newcode;
-        }
+        code = ArrayUtils.ensureCapacity(code, cp);
         code[cp++] = (byte)od;
     }
 
@@ -903,6 +899,8 @@
         if (o instanceof Double) return syms.doubleType;
         if (o instanceof ClassSymbol) return syms.classType;
         if (o instanceof Type.ArrayType) return syms.classType;
+        if (o instanceof Type.MethodType) return syms.methodTypeType;
+        if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
         throw new AssertionError(o);
     }
 
@@ -1245,12 +1243,8 @@
 
         if (stackMapBuffer == null) {
             stackMapBuffer = new StackMapFrame[20];
-        } else if (stackMapBuffer.length == stackMapBufferSize) {
-            StackMapFrame[] newStackMapBuffer =
-                new StackMapFrame[stackMapBufferSize << 1];
-            System.arraycopy(stackMapBuffer, 0, newStackMapBuffer,
-                             0, stackMapBufferSize);
-            stackMapBuffer = newStackMapBuffer;
+        } else {
+            stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
         }
         StackMapFrame frame =
             stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
@@ -1318,12 +1312,10 @@
 
         if (stackMapTableBuffer == null) {
             stackMapTableBuffer = new StackMapTableFrame[20];
-        } else if (stackMapTableBuffer.length == stackMapBufferSize) {
-            StackMapTableFrame[] newStackMapTableBuffer =
-                new StackMapTableFrame[stackMapBufferSize << 1];
-            System.arraycopy(stackMapTableBuffer, 0, newStackMapTableBuffer,
-                             0, stackMapBufferSize);
-            stackMapTableBuffer = newStackMapTableBuffer;
+        } else {
+            stackMapTableBuffer = ArrayUtils.ensureCapacity(
+                                    stackMapTableBuffer,
+                                    stackMapBufferSize);
         }
         stackMapTableBuffer[stackMapBufferSize++] =
                 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
@@ -1649,10 +1641,8 @@
         void lock(int register) {
             if (locks == null) {
                 locks = new int[20];
-            } else if (locks.length == nlocks) {
-                int[] newLocks = new int[locks.length << 1];
-                System.arraycopy(locks, 0, newLocks, 0, locks.length);
-                locks = newLocks;
+            } else {
+                locks = ArrayUtils.ensureCapacity(locks, nlocks);
             }
             locks[nlocks] = register;
             nlocks++;
@@ -1678,11 +1668,7 @@
             default:
                 break;
             }
-            if (stacksize+2 >= stack.length) {
-                Type[] newstack = new Type[2*stack.length];
-                System.arraycopy(stack, 0, newstack, 0, stack.length);
-                stack = newstack;
-            }
+            stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
             stack[stacksize++] = t;
             switch (width(t)) {
             case 1:
@@ -1869,13 +1855,7 @@
     /** Add a new local variable. */
     private void addLocalVar(VarSymbol v) {
         int adr = v.adr;
-        if (adr+1 >= lvar.length) {
-            int newlength = lvar.length << 1;
-            if (newlength <= adr) newlength = adr + 10;
-            LocalVar[] new_lvar = new LocalVar[newlength];
-            System.arraycopy(lvar, 0, new_lvar, 0, lvar.length);
-            lvar = new_lvar;
-        }
+        lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
         Assert.checkNull(lvar[adr]);
         if (pendingJumps != null) resolvePending();
         lvar[adr] = new LocalVar(v);
@@ -1955,11 +1935,8 @@
         if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
         if (varBuffer == null)
             varBuffer = new LocalVar[20];
-        else if (varBufferSize >= varBuffer.length) {
-            LocalVar[] newVarBuffer = new LocalVar[varBufferSize*2];
-            System.arraycopy(varBuffer, 0, newVarBuffer, 0, varBuffer.length);
-            varBuffer = newVarBuffer;
-        }
+        else
+            varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
         varBuffer[varBufferSize++] = var;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Thu Oct 11 17:00:54 2012 -0700
@@ -2103,6 +2103,8 @@
             result = res;
         } else if (sym.kind == VAR && sym.owner.kind == MTH) {
             result = items.makeLocalItem((VarSymbol)sym);
+        } else if (isInvokeDynamic(sym)) {
+            result = items.makeDynamicItem(sym);
         } else if ((sym.flags() & STATIC) != 0) {
             if (!isAccessSuper(env.enclMethod))
                 sym = binaryQualifier(sym, env.enclClass.type);
@@ -2152,8 +2154,12 @@
             result = items.
                 makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
         } else {
-            if (!accessSuper)
+            if (isInvokeDynamic(sym)) {
+                result = items.makeDynamicItem(sym);
+                return;
+            } else if (!accessSuper) {
                 sym = binaryQualifier(sym, tree.selected.type);
+            }
             if ((sym.flags() & STATIC) != 0) {
                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
                     base = base.load();
@@ -2174,6 +2180,10 @@
         }
     }
 
+    public boolean isInvokeDynamic(Symbol sym) {
+        return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
+    }
+
     public void visitLiteral(JCLiteral tree) {
         if (tree.type.tag == TypeTags.BOT) {
             code.emitop0(aconst_null);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -110,6 +110,13 @@
         return stackItem[Code.typecode(type)];
     }
 
+    /** Make an item representing a dynamically invoked method.
+     *  @param member   The represented symbol.
+     */
+    Item makeDynamicItem(Symbol member) {
+        return new DynamicItem(member);
+    }
+
     /** Make an item representing an indexed expression.
      *  @param type    The expression's type.
      */
@@ -457,6 +464,35 @@
         }
     }
 
+    /** An item representing a dynamic call site.
+     */
+    class DynamicItem extends StaticItem {
+        DynamicItem(Symbol member) {
+            super(member);
+        }
+
+        Item load() {
+            assert false;
+            return null;
+        }
+
+        void store() {
+            assert false;
+        }
+
+        Item invoke() {
+            // assert target.hasNativeInvokeDynamic();
+            MethodType mtype = (MethodType)member.erasure(types);
+            int rescode = Code.typecode(mtype.restype);
+            code.emitInvokedynamic(pool.put(member), mtype);
+            return stackItem[rescode];
+        }
+
+        public String toString() {
+            return "dynamic(" + member + ")";
+        }
+    }
+
     /** An item representing an instance variable or method.
      */
     class MemberItem extends Item {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Pool.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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,10 +25,17 @@
 
 package com.sun.tools.javac.jvm;
 
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+
+import com.sun.tools.javac.util.ArrayUtils;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Filter;
+import com.sun.tools.javac.util.Name;
+
 import java.util.*;
 
-import com.sun.tools.javac.code.Symbol.*;
-
 /** An internal structure that corresponds to the constant pool of a classfile.
  *
  *  <p><b>This is NOT part of any supported API.
@@ -83,14 +90,6 @@
         indices.clear();
     }
 
-    /** Double pool buffer in size.
-     */
-    private void doublePool() {
-        Object[] newpool = new Object[pool.length * 2];
-        System.arraycopy(pool, 0, newpool, 0, pool.length);
-        pool = newpool;
-    }
-
     /** Place an object in the pool, unless it is already there.
      *  If object is a symbol also enter its owner unless the owner is a
      *  package.  Return the object's index in the pool.
@@ -106,10 +105,10 @@
 //          System.err.println("put " + value + " " + value.getClass());//DEBUG
             index = pp;
             indices.put(value, index);
-            if (pp == pool.length) doublePool();
+            pool = ArrayUtils.ensureCapacity(pool, pp);
             pool[pp++] = value;
             if (value instanceof Long || value instanceof Double) {
-                if (pp == pool.length) doublePool();
+                pool = ArrayUtils.ensureCapacity(pool, pp);
                 pool[pp++] = null;
             }
         }
@@ -167,4 +166,86 @@
                 v.type.hashCode();
         }
     }
+
+    public static class MethodHandle {
+
+        /** Reference kind - see ClassFile */
+        int refKind;
+
+        /** Reference symbol */
+        Symbol refSym;
+
+        public MethodHandle(int refKind, Symbol refSym) {
+            this.refKind = refKind;
+            this.refSym = refSym;
+            checkConsistent();
+        }
+        public boolean equals(Object other) {
+            if (!(other instanceof MethodHandle)) return false;
+            MethodHandle mr = (MethodHandle) other;
+            if (mr.refKind != refKind)  return false;
+            Symbol o = mr.refSym;
+            return
+                o.name == refSym.name &&
+                o.owner == refSym.owner &&
+                o.type.equals(refSym.type);
+        }
+        public int hashCode() {
+            return
+                refKind * 65 +
+                refSym.name.hashCode() * 33 +
+                refSym.owner.hashCode() * 9 +
+                refSym.type.hashCode();
+        }
+
+        /**
+         * Check consistency of reference kind and symbol (see JVMS 4.4.8)
+         */
+        @SuppressWarnings("fallthrough")
+        private void checkConsistent() {
+            boolean staticOk = false;
+            int expectedKind = -1;
+            Filter<Name> nameFilter = nonInitFilter;
+            boolean interfaceOwner = false;
+            switch (refKind) {
+                case ClassFile.REF_getStatic:
+                case ClassFile.REF_putStatic:
+                    staticOk = true;
+                case ClassFile.REF_getField:
+                case ClassFile.REF_putField:
+                    expectedKind = Kinds.VAR;
+                    break;
+                case ClassFile.REF_newInvokeSpecial:
+                    nameFilter = initFilter;
+                    expectedKind = Kinds.MTH;
+                    break;
+                case ClassFile.REF_invokeInterface:
+                    interfaceOwner = true;
+                    expectedKind = Kinds.MTH;
+                    break;
+                case ClassFile.REF_invokeStatic:
+                    staticOk = true;
+                case ClassFile.REF_invokeVirtual:
+                case ClassFile.REF_invokeSpecial:
+                    expectedKind = Kinds.MTH;
+                    break;
+            }
+            Assert.check(!refSym.isStatic() || staticOk);
+            Assert.check(refSym.kind == expectedKind);
+            Assert.check(nameFilter.accepts(refSym.name));
+            Assert.check(!refSym.owner.isInterface() || interfaceOwner);
+        }
+        //where
+                Filter<Name> nonInitFilter = new Filter<Name>() {
+                    public boolean accepts(Name n) {
+                        return n != n.table.names.init && n != n.table.names.clinit;
+                    }
+                };
+
+                Filter<Name> initFilter = new Filter<Name>() {
+                    public boolean accepts(Name n) {
+                        return n == n.table.names.init;
+                    }
+                };
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Oct 11 17:00:54 2012 -0700
@@ -406,10 +406,17 @@
             ? names.fromString(options.get("failcomplete"))
             : null;
 
-        shouldStopPolicy =
-            options.isSet("shouldStopPolicy")
+        shouldStopPolicyIfError =
+            options.isSet("shouldStopPolicy") // backwards compatible
             ? CompileState.valueOf(options.get("shouldStopPolicy"))
-            : null;
+            : options.isSet("shouldStopPolicyIfError")
+            ? CompileState.valueOf(options.get("shouldStopPolicyIfError"))
+            : CompileState.INIT;
+        shouldStopPolicyIfNoError =
+            options.isSet("shouldStopPolicyIfNoError")
+            ? CompileState.valueOf(options.get("shouldStopPolicyIfNoError"))
+            : CompileState.GENERATE;
+
         if (options.isUnset("oldDiags"))
             log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
     }
@@ -486,12 +493,20 @@
     public boolean verboseCompilePolicy;
 
     /**
-     * Policy of how far to continue processing. null means until first
-     * error.
+     * Policy of how far to continue compilation after errors have occurred.
+     * Set this to minimum CompileState (INIT) to stop as soon as possible
+     * after errors.
      */
-    public CompileState shouldStopPolicy;
+    public CompileState shouldStopPolicyIfError;
 
-    /** A queue of all as yet unattributed classes.
+    /**
+     * Policy of how far to continue compilation when no errors have occurred.
+     * Set this to maximum CompileState (GENERATE) to perform full compilation.
+     * Set this lower to perform partial compilation, such as -proc:only.
+     */
+    public CompileState shouldStopPolicyIfNoError;
+
+    /** A queue of all as yet unattributed classes.oLo
      */
     public Todo todo;
 
@@ -501,6 +516,7 @@
 
     /** Ordered list of compiler phases for each compilation unit. */
     public enum CompileState {
+        INIT(0),
         PARSE(1),
         ENTER(2),
         PROCESS(3),
@@ -512,8 +528,11 @@
         CompileState(int value) {
             this.value = value;
         }
-        boolean isDone(CompileState other) {
-            return value >= other.value;
+        boolean isAfter(CompileState other) {
+            return value > other.value;
+        }
+        public static CompileState max(CompileState a, CompileState b) {
+            return a.value > b.value ? a : b;
         }
         private int value;
     };
@@ -524,7 +543,7 @@
         private static final long serialVersionUID = 1812267524140424433L;
         boolean isDone(Env<AttrContext> env, CompileState cs) {
             CompileState ecs = get(env);
-            return ecs != null && ecs.isDone(cs);
+            return (ecs != null) && !cs.isAfter(ecs);
         }
     }
     private CompileStates compileStates = new CompileStates();
@@ -536,10 +555,10 @@
     protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>();
 
     protected boolean shouldStop(CompileState cs) {
-        if (shouldStopPolicy == null)
-            return (errorCount() > 0 || unrecoverableError());
-        else
-            return cs.ordinal() > shouldStopPolicy.ordinal();
+        CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
+            ? shouldStopPolicyIfError
+            : shouldStopPolicyIfNoError;
+        return cs.isAfter(shouldStopPolicy);
     }
 
     /** The number of errors reported so far.
@@ -924,6 +943,18 @@
     }
 
     /**
+     * Enter the symbols found in a list of parse trees if the compilation
+     * is expected to proceed beyond anno processing into attr.
+     * As a side-effect, this puts elements on the "todo" list.
+     * Also stores a list of all top level classes in rootClasses.
+     */
+    public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
+       if (shouldStop(CompileState.ATTR))
+           return List.nil();
+        return enterTrees(roots);
+    }
+
+    /**
      * Enter the symbols found in a list of parse trees.
      * As a side-effect, this puts elements on the "todo" list.
      * Also stores a list of all top level classes in rootClasses.
@@ -1010,7 +1041,7 @@
                 genEndPos = true;
                 if (!taskListener.isEmpty())
                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
-                log.deferDiagnostics = true;
+                log.deferAll();
             } else { // free resources
                 procEnvImpl.close();
             }
@@ -1120,7 +1151,7 @@
                 if (c != this)
                     annotationProcessingOccurred = c.annotationProcessingOccurred = true;
                 // doProcessing will have handled deferred diagnostics
-                Assert.check(c.log.deferDiagnostics == false
+                Assert.check(c.log.deferredDiagFilter == null
                         && c.log.deferredDiagnostics.size() == 0);
                 return c;
             } finally {
@@ -1196,7 +1227,7 @@
             if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
                 //if in fail-over mode, ensure that AST expression nodes
                 //are correctly initialized (e.g. they have a type/symbol)
-                attr.postAttr(env);
+                attr.postAttr(env.tree);
             }
             compileStates.put(env, CompileState.ATTR);
         }
@@ -1648,6 +1679,8 @@
         hasBeenUsed = true;
         closeables = prev.closeables;
         prev.closeables = List.nil();
+        shouldStopPolicyIfError = prev.shouldStopPolicyIfError;
+        shouldStopPolicyIfNoError = prev.shouldStopPolicyIfNoError;
     }
 
     public static void enableLogging() {
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Thu Oct 11 17:00:54 2012 -0700
@@ -638,10 +638,6 @@
                         lexError(pos, "unclosed.str.lit");
                     }
                     break loop;
-                case '#':
-                    reader.scanChar();
-                    tk = TokenKind.HASH;
-                    break loop;
                 default:
                     if (isSpecial(reader.ch)) {
                         scanOperator();
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 11 17:00:54 2012 -0700
@@ -950,12 +950,13 @@
             break;
         case LPAREN:
             if (typeArgs == null && (mode & EXPR) != 0) {
-                if (peekToken(FINAL) ||
+                if (peekToken(MONKEYS_AT) ||
+                        peekToken(FINAL) ||
                         peekToken(RPAREN) ||
                         peekToken(IDENTIFIER, COMMA) ||
                         peekToken(IDENTIFIER, RPAREN, ARROW)) {
                     //implicit n-ary lambda
-                    t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos);
+                    t = lambdaExpressionOrStatement(true, peekToken(MONKEYS_AT) || peekToken(FINAL), pos);
                     break;
                 } else {
                     nextToken();
@@ -1159,7 +1160,7 @@
                     case LT:
                         if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
                             //this is an unbound method reference whose qualifier
-                            //is a generic type i.e. A<S>#m
+                            //is a generic type i.e. A<S>::m
                             int pos1 = token.pos;
                             accept(LT);
                             ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
@@ -1177,7 +1178,8 @@
                                 t = toP(F.at(token.pos).Select(t, ident()));
                                 t = typeArgumentsOpt(t);
                             }
-                            if (token.kind != HASH) {
+                            t = bracketsOpt(t);
+                            if (token.kind != COLCOL) {
                                 //method reference expected here
                                 t = illegal();
                             }
@@ -1237,6 +1239,10 @@
                         nextToken();
                         t = bracketsOpt(t);
                         t = toP(F.at(pos1).TypeArray(t));
+                        if (token.kind == COLCOL) {
+                            mode = EXPR;
+                            continue;
+                        }
                         return t;
                     }
                     mode = oldmode;
@@ -1269,10 +1275,10 @@
                     t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
                     typeArgs = null;
                 }
-            } else if ((mode & EXPR) != 0 && token.kind == HASH) {
+            } else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
                 mode = EXPR;
                 if (typeArgs != null) return illegal();
-                accept(HASH);
+                accept(COLCOL);
                 t = memberReferenceSuffix(pos1, t);
             } else {
                 break;
@@ -1311,9 +1317,11 @@
                 case GT:
                     depth--;
                     if (depth == 0) {
+                        TokenKind nextKind = S.token(pos + 1).kind;
                         return
-                            S.token(pos + 1).kind == TokenKind.DOT ||
-                            S.token(pos + 1).kind == TokenKind.HASH;
+                            nextKind == TokenKind.DOT ||
+                            nextKind == TokenKind.LBRACKET ||
+                            nextKind == TokenKind.COLCOL;
                     }
                     break;
                 default:
@@ -1343,11 +1351,6 @@
     }
 
     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
-        if (token.kind != ARROW) {
-            //better error recovery
-            return F.at(pos).Erroneous(args);
-        }
-
         checkLambda();
         accept(ARROW);
 
@@ -1372,7 +1375,7 @@
         nextToken();
         if (token.kind == LPAREN || typeArgs != null) {
             t = arguments(typeArgs, t);
-        } else if (token.kind == HASH) {
+        } else if (token.kind == COLCOL) {
             if (typeArgs != null) return illegal();
             t = memberReferenceSuffix(t);
         } else {
@@ -1583,20 +1586,22 @@
                 t = toP(F.at(pos).Select(t, names._class));
             }
         } else if ((mode & TYPE) != 0) {
-            mode = TYPE;
-        } else {
+            if (token.kind != COLCOL) {
+                mode = TYPE;
+            }
+        } else if (token.kind != COLCOL) {
             syntaxError(token.pos, "dot.class.expected");
         }
         return t;
     }
 
     /**
-     * MemberReferenceSuffix = "#" [TypeArguments] Ident
-     *                       | "#" [TypeArguments] "new"
+     * MemberReferenceSuffix = "::" [TypeArguments] Ident
+     *                       | "::" [TypeArguments] "new"
      */
     JCExpression memberReferenceSuffix(JCExpression t) {
         int pos1 = token.pos;
-        accept(HASH);
+        accept(COLCOL);
         return memberReferenceSuffix(pos1, t);
     }
 
@@ -2165,27 +2170,10 @@
         while (true) {
             int pos = token.pos;
             switch (token.kind) {
-            case CASE: {
-                nextToken();
-                JCExpression pat = parseExpression();
-                accept(COLON);
-                List<JCStatement> stats = blockStatements();
-                JCCase c = F.at(pos).Case(pat, stats);
-                if (stats.isEmpty())
-                    storeEnd(c, S.prevToken().endPos);
-                cases.append(c);
+            case CASE:
+            case DEFAULT:
+                cases.append(switchBlockStatementGroup());
                 break;
-            }
-            case DEFAULT: {
-                nextToken();
-                accept(COLON);
-                List<JCStatement> stats = blockStatements();
-                JCCase c = F.at(pos).Case(null, stats);
-                if (stats.isEmpty())
-                    storeEnd(c, S.prevToken().endPos);
-                cases.append(c);
-                break;
-            }
             case RBRACE: case EOF:
                 return cases.toList();
             default:
@@ -2196,6 +2184,32 @@
         }
     }
 
+    protected JCCase switchBlockStatementGroup() {
+        int pos = token.pos;
+        List<JCStatement> stats;
+        JCCase c;
+        switch (token.kind) {
+        case CASE:
+            nextToken();
+            JCExpression pat = parseExpression();
+            accept(COLON);
+            stats = blockStatements();
+            c = F.at(pos).Case(pat, stats);
+            if (stats.isEmpty())
+                storeEnd(c, S.prevToken().endPos);
+            return c;
+        case DEFAULT:
+            nextToken();
+            accept(COLON);
+            stats = blockStatements();
+            c = F.at(pos).Case(null, stats);
+            if (stats.isEmpty())
+                storeEnd(c, S.prevToken().endPos);
+            return c;
+        }
+        throw new AssertionError("should not reach here");
+    }
+
     /** MoreStatementExpressions = { COMMA StatementExpression }
      */
     <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java	Thu Oct 11 17:00:54 2012 -0700
@@ -177,7 +177,7 @@
         FALSE("false", Tag.NAMED),
         NULL("null", Tag.NAMED),
         ARROW("->"),
-        HASH("#"),
+        COLCOL("::"),
         LPAREN("("),
         RPAREN(")"),
         LBRACE("{"),
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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,13 +25,15 @@
 
 package com.sun.tools.javac.parser;
 
+import java.nio.CharBuffer;
+import java.util.Arrays;
+
 import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.ArrayUtils;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 
-import java.nio.CharBuffer;
-
 import static com.sun.tools.javac.util.LayoutCharacters.*;
 
 /** The char reader used by the javac lexer/tokenizer. Returns the sequence of
@@ -91,9 +93,7 @@
             if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
                 inputLength--;
             } else {
-                char[] newInput = new char[inputLength + 1];
-                System.arraycopy(input, 0, newInput, 0, input.length);
-                input = newInput;
+                input = Arrays.copyOf(input, inputLength + 1);
             }
         }
         buf = input;
@@ -130,11 +130,7 @@
     /** Append a character to sbuf.
      */
     protected void putChar(char ch, boolean scan) {
-        if (sp == sbuf.length) {
-            char[] newsbuf = new char[sbuf.length * 2];
-            System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
-            sbuf = newsbuf;
-        }
+        sbuf = ArrayUtils.ensureCapacity(sbuf, sp);
         sbuf[sp++] = ch;
         if (scan)
             scanChar();
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Oct 11 17:00:54 2012 -0700
@@ -49,7 +49,7 @@
 
 import com.sun.source.util.JavacTask;
 import com.sun.source.util.TaskEvent;
-import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.BasicJavacTask;
 import com.sun.tools.javac.api.JavacTrees;
 import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
@@ -97,11 +97,9 @@
     private final boolean printRounds;
     private final boolean verbose;
     private final boolean lint;
-    private final boolean procOnly;
     private final boolean fatalErrors;
     private final boolean werror;
     private final boolean showResolveErrors;
-    private boolean foundTypeProcessors;
 
     private final JavacFiler filer;
     private final JavacMessager messager;
@@ -167,12 +165,14 @@
         printRounds = options.isSet(XPRINTROUNDS);
         verbose = options.isSet(VERBOSE);
         lint = Lint.instance(context).isEnabled(PROCESSING);
-        procOnly = options.isSet(PROC, "only") || options.isSet(XPRINT);
+        if (options.isSet(PROC, "only") || options.isSet(XPRINT)) {
+            JavaCompiler compiler = JavaCompiler.instance(context);
+            compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
+        }
         fatalErrors = options.isSet("fatalEnterError");
         showResolveErrors = options.isSet("showResolveErrors");
         werror = options.isSet(WERROR);
         platformAnnotations = initPlatformAnnotations();
-        foundTypeProcessors = false;
 
         // Initialize services before any processors are initialized
         // in case processors use them.
@@ -462,7 +462,7 @@
      * State about how a processor has been used by the tool.  If a
      * processor has been used on a prior round, its process method is
      * called on all subsequent rounds, perhaps with an empty set of
-     * annotations to process.  The {@code annotatedSupported} method
+     * annotations to process.  The {@code annotationSupported} method
      * caches the supported annotation information from the first (and
      * only) getSupportedAnnotationTypes call to the processor.
      */
@@ -806,7 +806,7 @@
             log = Log.instance(context);
             log.nerrors = priorErrors;
             log.nwarnings += priorWarnings;
-            log.deferDiagnostics = true;
+            log.deferAll();
 
             // the following is for the benefit of JavacProcessingEnvironment.getContext()
             JavacProcessingEnvironment.this.context = context;
@@ -882,7 +882,9 @@
         /** Create the compiler to be used for the final compilation. */
         JavaCompiler finalCompiler(boolean errorStatus) {
             try {
-                JavaCompiler c = JavaCompiler.instance(nextContext());
+                Context nextCtx = nextContext();
+                JavacProcessingEnvironment.this.context = nextCtx;
+                JavaCompiler c = JavaCompiler.instance(nextCtx);
                 c.log.nwarnings += compiler.log.nwarnings;
                 if (errorStatus) {
                     c.log.nerrors += compiler.log.nerrors;
@@ -1021,7 +1023,7 @@
         }
 
         /** Get the context for the next round of processing.
-         * Important values are propogated from round to round;
+         * Important values are propagated from round to round;
          * other values are implicitly reset.
          */
         private Context nextContext() {
@@ -1086,10 +1088,11 @@
             elementUtils.setContext(next);
             typeUtils.setContext(next);
 
-            JavacTaskImpl task = (JavacTaskImpl) context.get(JavacTask.class);
+            JavacTask task = context.get(JavacTask.class);
             if (task != null) {
                 next.put(JavacTask.class, task);
-                task.updateContext(next);
+                if (task instanceof BasicJavacTask)
+                    ((BasicJavacTask) task).updateContext(next);
             }
 
             JavacTrees trees = context.get(JavacTrees.class);
@@ -1189,14 +1192,7 @@
             return compiler;
         }
 
-        if (procOnly && !foundTypeProcessors) {
-            compiler.todo.clear();
-        } else {
-            if (procOnly && foundTypeProcessors)
-                compiler.shouldStopPolicy = CompileState.FLOW;
-
-            compiler.enterTrees(roots);
-        }
+        compiler.enterTreesIfNeeded(roots);
 
         return compiler;
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Oct 11 17:00:54 2012 -0700
@@ -148,13 +148,8 @@
 compiler.err.call.must.be.first.stmt.in.ctor=\
     call to {0} must be first statement in constructor
 
+# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment
 compiler.err.cant.apply.symbol=\
-    {0} {1} in {4} {5} cannot be applied to given types\n\
-    required: {2}\n\
-    found: {3}
-
-# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment
-compiler.err.cant.apply.symbol.1=\
     {0} {1} in {4} {5} cannot be applied to given types;\n\
     required: {2}\n\
     found: {3}\n\
@@ -164,6 +159,74 @@
 compiler.err.cant.apply.symbols=\
     no suitable {0} found for {1}({2})
 
+# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment
+compiler.misc.cant.apply.symbol=\
+    {0} {1} in {4} {5} cannot be applied to given types\n\
+    required: {2}\n\
+    found: {3}\n\
+    reason: {6}
+
+# 0: symbol kind, 1: name, 2: list of type
+compiler.misc.cant.apply.symbols=\
+    no suitable {0} found for {1}({2})
+
+
+# 0: type
+compiler.err.cant.access.arg.type.in.functional.desc=\
+    cannot access parameter type {0} in target functional descriptor
+
+# 0: type
+compiler.err.cant.access.return.in.functional.desc=\
+    cannot access return type {0} in target functional descriptor
+
+# 0: type
+compiler.err.cant.access.thrown.in.functional.desc=\
+    cannot access thrown type {0} in target functional descriptor
+
+# 0: symbol kind, 1: symbol
+compiler.misc.no.abstracts=\
+    no abstract method found in {0} {1}
+
+# 0: symbol kind, 1: symbol
+compiler.misc.incompatible.abstracts=\
+    multiple non-overriding abstract methods found in {0} {1}
+
+compiler.misc.not.a.functional.intf=\
+    the target type must be a functional interface
+
+# 0: message segment
+compiler.misc.not.a.functional.intf.1=\
+    the target type must be a functional interface\n\
+    {0}
+
+# 0: symbol, 1: symbol kind, 2: symbol
+compiler.misc.invalid.generic.desc.in.functional.intf=\
+    invalid functional descriptor: method {0} in {1} {2} is generic
+
+# 0: symbol kind, 1: symbol
+compiler.misc.incompatible.descs.in.functional.intf=\
+    incompatible function descriptors found in {0} {1}
+
+# 0: name, 1: list of type, 2: type, 3: list of type
+compiler.misc.descriptor=\
+    descriptor: {2} {0}({1})
+
+# 0: name, 1: list of type, 2: type, 3: list of type
+compiler.misc.descriptor.throws=\
+    descriptor: {2} {0}({1}) throws {3}
+
+# 0: type
+compiler.misc.no.suitable.functional.intf.inst=\
+    cannot infer functional interface descriptor for {0}
+
+# 0: symbol kind, 1: message segment
+compiler.err.invalid.mref=\
+    invalid {0} reference; {1}
+
+# 0: symbol kind, 1: message segment
+compiler.misc.invalid.mref=\
+    invalid {0} reference; {1}
+
 # 0: symbol
 compiler.err.cant.assign.val.to.final.var=\
     cannot assign a value to final variable {0}
@@ -173,6 +236,9 @@
     local variables referenced from {1} must be final or effectively final
 
 
+compiler.misc.lambda=\
+    a lambda expression
+
 compiler.misc.inner.cls=\
     an inner class
 
@@ -292,7 +358,7 @@
 
 # 0: type, 1: symbol
 compiler.err.invalid.containedby.annotation.elem.nondefault=\
-    duplicate annotation, element {1} in containing annotation {0} does not have a default value
+    containing annotation {0} does not have a default value for element {1}
 
 # 0: symbol, 1: type, 2: symbol, 3: type
 compiler.err.invalid.containedby.annotation.retention=\
@@ -592,6 +658,9 @@
 compiler.err.missing.ret.stmt=\
     missing return statement
 
+compiler.misc.missing.ret.val=\
+    missing return value
+
 compiler.err.missing.ret.val=\
     missing return value
 
@@ -635,6 +704,31 @@
     second operand: {0}\n\
     third operand : {1}
 
+# 0: message segment
+compiler.misc.incompatible.type.in.conditional=\
+    bad type in conditional expression; {0}
+
+# 0: type
+compiler.misc.incompatible.ret.type.in.lambda=\
+    bad return type in lambda expression\n\
+    {0}
+
+# 0: type
+compiler.misc.incompatible.ret.type.in.mref=\
+    bad return type in method reference\n\
+    {0}
+
+# 0: list of type
+compiler.err.incompatible.thrown.types.in.lambda=\
+    incompatible thrown types {0} in lambda expression
+
+# 0: list of type
+compiler.err.incompatible.thrown.types.in.mref=\
+    incompatible thrown types {0} in method reference
+
+compiler.misc.incompatible.arg.types.in.lambda=\
+    incompatible parameter types in lambda expression
+
 compiler.err.new.not.allowed.in.annotation=\
     ''new'' not allowed in an annotation
 
@@ -658,6 +752,15 @@
     {0} in {1} is defined in an inaccessible class or interface
 
 # 0: symbol, 1: symbol
+compiler.misc.not.def.access.class.intf.cant.access=\
+    {0} in {1} is defined in an inaccessible class or interface
+
+# 0: symbol, 1: list of type, 2: type
+compiler.misc.cant.access.inner.cls.constr=\
+    cannot access constructor {0}({1})\n\
+    an enclosing instance of type {2} is not in scope
+
+# 0: symbol, 1: symbol
 compiler.err.not.def.public.cant.access=\
     {0} is not public in {1}; cannot be accessed from outside package
 
@@ -755,7 +858,13 @@
 
 # 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol
 compiler.err.ref.ambiguous=\
-    reference to {0} is ambiguous, both {1} {2} in {3} and {4} {5} in {6} match
+    reference to {0} is ambiguous\n\
+    both {1} {2} in {3} and {4} {5} in {6} match
+
+# 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol
+compiler.misc.ref.ambiguous=\
+    reference to {0} is ambiguous\n\
+    both {1} {2} in {3} and {4} {5} in {6} match
 
 compiler.err.repeated.annotation.target=\
     repeated annotation target
@@ -991,6 +1100,10 @@
 
 ## The following string will appear before all messages keyed as:
 ## "compiler.note".
+
+compiler.note.potential.lambda.found=\
+    This anonymous inner class creation can be turned into a lambda expression.
+
 compiler.note.note=\
     Note:\u0020
 
@@ -1652,6 +1765,18 @@
 compiler.misc.incompatible.upper.bounds=\
     inference variable {0} has incompatible upper bounds {1}
 
+# 0: type, 1: list of type, 2: list of type
+compiler.misc.incompatible.eq.upper.bounds=\
+    inference variable {0} has incompatible bounds\n\
+    equality constraints: {1}\n\
+    upper bounds: {2}
+
+# 0: type, 1: list of type, 2: list of type
+compiler.misc.incompatible.eq.lower.bounds=\
+    inference variable {0} has incompatible bounds\n\
+    equality constraints: {1}\n\
+    lower bounds: {2}
+
 # 0: list of type, 1: type, 2: type
 compiler.misc.infer.no.conforming.instance.exists=\
     no instance(s) of type variable(s) {0} exist so that {1} conforms to {2}
@@ -1689,6 +1814,10 @@
     inferred: {0}\n\
     equality constraints(s): {1}
 
+# 0: list of type
+compiler.misc.cyclic.inference=\
+    Cannot instantiate inference variables {0} because of an inference loop
+
 # 0: symbol
 compiler.misc.diamond=\
     {0}<>
@@ -1728,6 +1857,10 @@
 compiler.err.non-static.cant.be.ref=\
     non-static {0} {1} cannot be referenced from a static context
 
+# 0: symbol kind, 1: symbol
+compiler.misc.non-static.cant.be.ref=\
+    non-static {0} {1} cannot be referenced from a static context
+
 ## Both arguments ({0}, {1}) are "kindname"s.  {0} is a comma-separated list
 ## of kindnames (the list should be identical to that provided in source.
 compiler.err.unexpected.type=\
@@ -1735,6 +1868,12 @@
     required: {0}\n\
     found:    {1}
 
+compiler.err.unexpected.lambda=\
+   lambda expression not expected here
+
+compiler.err.unexpected.mref=\
+   method reference not expected here
+
 ## The first argument {0} is a "kindname" (e.g. 'constructor', 'field', etc.)
 ## The second argument {1} is the non-resolved symbol
 ## The third argument {2} is a list of type parameters (non-empty if {1} is a method)
@@ -1774,6 +1913,20 @@
     symbol:   {0} <{2}>{1}({3})\n\
     location: {4}
 
+### Following are replicated/used for method reference diagnostics
+
+# 0: symbol kind, 1: name, 2: unused, 3: list of type, 4: message segment
+compiler.misc.cant.resolve.location.args=\
+    cannot find symbol\n\
+    symbol:   {0} {1}({3})\n\
+    location: {4}
+
+# 0: symbol kind, 1: name, 2: list of type, 3: list, 4: message segment
+compiler.misc.cant.resolve.location.args.params=\
+    cannot find symbol\n\
+    symbol:   {0} <{2}>{1}({3})\n\
+    location: {4}
+
 ##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
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1810,11 +1810,46 @@
      */
     public static class JCMemberReference extends JCExpression implements MemberReferenceTree {
         public ReferenceMode mode;
+        public ReferenceKind kind;
         public Name name;
         public JCExpression expr;
         public List<JCExpression> typeargs;
         public Type targetType;
         public Symbol sym;
+        public Type varargsElement;
+
+        /**
+         * Javac-dependent classification for member references, based
+         * on relevant properties w.r.t. code-generation
+         */
+        public enum ReferenceKind {
+            /** super # instMethod */
+            SUPER(ReferenceMode.INVOKE, false),
+            /** Type # instMethod */
+            UNBOUND(ReferenceMode.INVOKE, true),
+            /** Type # staticMethod */
+            STATIC(ReferenceMode.INVOKE, false),
+            /** Expr # instMethod */
+            BOUND(ReferenceMode.INVOKE, false),
+            /** Expr # staticMethod */
+            STATIC_EVAL(ReferenceMode.INVOKE, false),
+            /** Inner # new */
+            IMPLICIT_INNER(ReferenceMode.NEW, false),
+            /** Toplevel # new */
+            TOPLEVEL(ReferenceMode.NEW, false);
+
+            ReferenceMode mode;
+            boolean unbound;
+
+            private ReferenceKind(ReferenceMode mode, boolean unbound) {
+                this.mode = mode;
+                this.unbound = unbound;
+            }
+
+            public boolean isUnbound() {
+                return unbound;
+            }
+        }
 
         protected JCMemberReference(ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
             this.mode = mode;
@@ -1843,6 +1878,9 @@
         public Tag getTag() {
             return REFERENCE;
         }
+        public boolean hasKind(ReferenceKind kind) {
+            return this.kind == kind;
+        }
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu Oct 11 17:00:54 2012 -0700
@@ -81,6 +81,17 @@
      */
     DocCommentTable docComments = null;
 
+    /**
+     * A string sequence to be used when Pretty output should be constrained
+     * to fit into a given size
+     */
+    private final static String trimSequence = "[...]";
+
+    /**
+     * Max number of chars to be generated when output should fit into a single line
+     */
+    private final static int PREFERRED_LENGTH = 20;
+
     /** Align code to be indented to left margin.
      */
     void align() throws IOException {
@@ -129,6 +140,31 @@
         out.write(lineSep);
     }
 
+    public static String toSimpleString(JCTree tree) {
+        return toSimpleString(tree, PREFERRED_LENGTH);
+    }
+
+    public static String toSimpleString(JCTree tree, int maxLength) {
+        StringWriter s = new StringWriter();
+        try {
+            new Pretty(s, false).printExpr(tree);
+        }
+        catch (IOException e) {
+            // should never happen, because StringWriter is defined
+            // never to throw any IOExceptions
+            throw new AssertionError(e);
+        }
+        //we need to (i) replace all line terminators with a space and (ii) remove
+        //occurrences of 'missing' in the Pretty output (generated when types are missing)
+        String res = s.toString().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
+        if (res.length() < maxLength) {
+            return res;
+        } else {
+            int split = (maxLength - trimSequence.length()) * 2 / 3;
+            return res.substring(0, split) + trimSequence + res.substring(split);
+        }
+    }
+
     String lineSep = System.getProperty("line.separator");
 
     /**************************************************************************
@@ -911,7 +947,16 @@
     public void visitLambda(JCLambda tree) {
         try {
             print("(");
-            printExprs(tree.params);
+            if (TreeInfo.isExplicitLambda(tree)) {
+                printExprs(tree.params);
+            } else {
+                String sep = "";
+                for (JCVariableDecl param : tree.params) {
+                    print(sep);
+                    print(param.name);
+                    sep = ",";
+                }
+            }
             print(")->");
             printExpr(tree.body);
         } catch (IOException e) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Thu Oct 11 17:00:54 2012 -0700
@@ -245,6 +245,27 @@
         }
     }
 
+    /** Return true if a a tree corresponds to a poly expression. */
+    public static boolean isPoly(JCTree tree, JCTree origin) {
+        switch (tree.getTag()) {
+            case APPLY:
+            case NEWCLASS:
+            case CONDEXPR:
+                return !origin.hasTag(TYPECAST);
+            case LAMBDA:
+            case REFERENCE:
+                return true;
+            case PARENS:
+                return isPoly(((JCParens)tree).expr, origin);
+            default:
+                return false;
+        }
+    }
+
+    public static boolean isExplicitLambda(JCLambda lambda) {
+        return lambda.params.isEmpty() ||
+                lambda.params.head.vartype != null;
+    }
     /**
      * Return true if the AST corresponds to a static select of the kind A.B
      */
@@ -261,6 +282,7 @@
                 return isStaticSym(base) &&
                     isStaticSelector(((JCFieldAccess)base).selected, names);
             case TYPEAPPLY:
+            case TYPEARRAY:
                 return true;
             default:
                 return false;
@@ -383,6 +405,10 @@
                 JCVariableDecl node = (JCVariableDecl)tree;
                 if (node.mods.pos != Position.NOPOS) {
                     return node.mods.pos;
+                } else if (node.vartype == null) {
+                    //if there's no type (partially typed lambda parameter)
+                    //simply return node position
+                    return node.pos;
                 } else {
                     return getStartPos(node.vartype);
                 }
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -43,8 +43,10 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Type.CapturedType;
+import com.sun.tools.javac.tree.JCTree.*;
 
 import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.tree.Pretty;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
 
 /**
@@ -180,6 +182,9 @@
             }
             return s;
         }
+        else if (arg instanceof JCExpression) {
+            return expr2String((JCExpression)arg);
+        }
         else if (arg instanceof Iterable<?>) {
             return formatIterable(d, (Iterable<?>)arg, l);
         }
@@ -199,6 +204,20 @@
             return String.valueOf(arg);
         }
     }
+    //where
+            private String expr2String(JCExpression tree) {
+                switch(tree.getTag()) {
+                    case PARENS:
+                        return expr2String(((JCParens)tree).expr);
+                    case LAMBDA:
+                    case REFERENCE:
+                    case CONDEXPR:
+                        return Pretty.toSimpleString(tree);
+                    default:
+                        Assert.error("unexpected tree kind " + tree.getKind());
+                        return null;
+                }
+            }
 
     /**
      * Format an iterable argument of a given diagnostic.
@@ -490,6 +509,7 @@
      * lead to infinite loops.
      */
     protected Printer printer = new Printer() {
+
         @Override
         protected String localize(Locale locale, String key, Object... args) {
             return AbstractDiagnosticFormatter.this.localize(locale, key, args);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/ArrayUtils.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1999, 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+import java.lang.reflect.Array;
+
+/** <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class ArrayUtils {
+
+    private static int calculateNewLength(int currentLength, int maxIndex) {
+        while (currentLength < maxIndex + 1)
+            currentLength = currentLength * 2;
+        return currentLength;
+    }
+
+    public static <T> T[] ensureCapacity(T[] array, int maxIndex) {
+        if (maxIndex < array.length) {
+            return array;
+        } else {
+            int newLength = calculateNewLength(array.length, maxIndex);
+            @SuppressWarnings("unchecked")
+            T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), newLength);
+            System.arraycopy(array, 0, result, 0, array.length);
+            return result;
+        }
+    }
+
+    public static byte[] ensureCapacity(byte[] array, int maxIndex) {
+        if (maxIndex < array.length) {
+            return array;
+        } else {
+            int newLength = calculateNewLength(array.length, maxIndex);
+            byte[] result = new byte[newLength];
+            System.arraycopy(array, 0, result, 0, array.length);
+            return result;
+        }
+    }
+
+    public static char[] ensureCapacity(char[] array, int maxIndex) {
+        if (maxIndex < array.length) {
+            return array;
+        } else {
+            int newLength = calculateNewLength(array.length, maxIndex);
+            char[] result = new char[newLength];
+            System.arraycopy(array, 0, result, 0, array.length);
+            return result;
+        }
+    }
+
+    public static int[] ensureCapacity(int[] array, int maxIndex) {
+        if (maxIndex < array.length) {
+            return array;
+        } else {
+            int newLength = calculateNewLength(array.length, maxIndex);
+            int[] result = new int[newLength];
+            System.arraycopy(array, 0, result, 0, array.length);
+            return result;
+        }
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java	Thu Oct 11 17:00:54 2012 -0700
@@ -25,6 +25,8 @@
 
 package com.sun.tools.javac.util;
 
+import java.util.Arrays;
+
 /** A class for extensible, mutable bit sets.
  *
  *  <p><b>This is NOT part of any supported API.
@@ -62,9 +64,7 @@
 
     private void sizeTo(int len) {
         if (bits.length < len) {
-            int[] newbits = new int[len];
-            System.arraycopy(bits, 0, newbits, 0, bits.length);
-            bits = newbits;
+            bits = Arrays.copyOf(bits, len);
         }
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/util/ByteBuffer.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/ByteBuffer.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -60,16 +60,10 @@
         length = 0;
     }
 
-    private void copy(int size) {
-        byte[] newelems = new byte[size];
-        System.arraycopy(elems, 0, newelems, 0, elems.length);
-        elems = newelems;
-    }
-
     /** Append byte to this buffer.
      */
     public void appendByte(int b) {
-        if (length >= elems.length) copy(elems.length * 2);
+        elems = ArrayUtils.ensureCapacity(elems, length);
         elems[length++] = (byte)b;
     }
 
@@ -77,7 +71,7 @@
      *  starting at given `start' offset.
      */
     public void appendBytes(byte[] bs, int start, int len) {
-        while (length + len > elems.length) copy(elems.length * 2);
+        elems = ArrayUtils.ensureCapacity(elems, length + len);
         System.arraycopy(bs, start, elems, length, len);
         length += len;
     }
@@ -91,7 +85,7 @@
     /** Append a character as a two byte number.
      */
     public void appendChar(int x) {
-        while (length + 1 >= elems.length) copy(elems.length * 2);
+        elems = ArrayUtils.ensureCapacity(elems, length + 1);
         elems[length  ] = (byte)((x >>  8) & 0xFF);
         elems[length+1] = (byte)((x      ) & 0xFF);
         length = length + 2;
@@ -100,7 +94,7 @@
     /** Append an integer as a four byte number.
      */
     public void appendInt(int x) {
-        while (length + 3 >= elems.length) copy(elems.length * 2);
+        elems = ArrayUtils.ensureCapacity(elems, length + 3);
         elems[length  ] = (byte)((x >> 24) & 0xFF);
         elems[length+1] = (byte)((x >> 16) & 0xFF);
         elems[length+2] = (byte)((x >>  8) & 0xFF);
--- a/langtools/src/share/classes/com/sun/tools/javac/util/List.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/List.java	Thu Oct 11 17:00:54 2012 -0700
@@ -83,6 +83,19 @@
         }
     };
 
+    /** Returns the list obtained from 'l' after removing all elements 'elem'
+     */
+    public static <A> List<A> filter(List<A> l, A elem) {
+        Assert.checkNonNull(elem);
+        List<A> res = List.nil();
+        for (A a : l) {
+            if (a != null && !a.equals(elem)) {
+                res = res.prepend(a);
+            }
+        }
+        return res.reverse();
+    }
+
     /** Construct a list consisting of given element.
      */
     public static <A> List<A> of(A x1) {
@@ -120,6 +133,14 @@
         return xs;
     }
 
+    public static <A> List<A> from(Iterable<? extends A> coll) {
+        List<A> xs = nil();
+        for (A a : coll) {
+            xs = new List<A>(a, xs);
+        }
+        return xs;
+    }
+
     /** Construct a list consisting of a given number of identical elements.
      *  @param len    The number of elements in the list.
      *  @param init   The value of each element.
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java	Thu Oct 11 17:00:54 2012 -0700
@@ -130,7 +130,7 @@
     /**
      * Deferred diagnostics
      */
-    public boolean deferDiagnostics;
+    public Filter<JCDiagnostic> deferredDiagFilter;
     public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>();
 
     /** Construct a log with given I/O redirections.
@@ -450,7 +450,7 @@
 
     /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */
     public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
-        deferDiagnostics = false;
+        deferredDiagFilter = null;
         JCDiagnostic d;
         while ((d = deferredDiagnostics.poll()) != null) {
             if (kinds.contains(d.getKind()))
@@ -464,7 +464,7 @@
      * reported so far, the diagnostic may be handed off to writeDiagnostic.
      */
     public void report(JCDiagnostic diagnostic) {
-        if (deferDiagnostics) {
+        if (deferredDiagFilter != null && deferredDiagFilter.accepts(diagnostic)) {
             deferredDiagnostics.add(diagnostic);
             return;
         }
@@ -551,6 +551,18 @@
         }
     }
 
+    public void deferAll() {
+        deferredDiagFilter = new Filter<JCDiagnostic>() {
+            public boolean accepts(JCDiagnostic t) {
+                return true;
+            }
+        };
+    }
+
+    public void deferNone() {
+        deferredDiagFilter = null;
+    }
+
     /** Find a localized string in the resource bundle.
      *  Because this method is static, it ignores the locale.
      *  Use localize(key, args) when possible.
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java	Thu Oct 11 17:00:54 2012 -0700
@@ -118,6 +118,7 @@
     // attribute names
     public final Name Annotation;
     public final Name AnnotationDefault;
+    public final Name BootstrapMethods;
     public final Name Bridge;
     public final Name CharacterRangeTable;
     public final Name Code;
@@ -246,6 +247,7 @@
         // attribute names
         Annotation = fromString("Annotation");
         AnnotationDefault = fromString("AnnotationDefault");
+        BootstrapMethods = fromString("BootstrapMethods");
         Bridge = fromString("Bridge");
         CharacterRangeTable = fromString("CharacterRangeTable");
         Code = fromString("Code");
--- a/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -32,6 +32,7 @@
 import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*;
 import com.sun.tools.javac.api.Formattable;
 import com.sun.tools.javac.file.BaseFileObject;
+import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
 
 import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
@@ -117,16 +118,17 @@
     @Override
     protected String formatArgument(JCDiagnostic diag, Object arg, Locale l) {
         String s;
-        if (arg instanceof Formattable)
+        if (arg instanceof Formattable) {
             s = arg.toString();
-        else if (arg instanceof BaseFileObject)
+        } else if (arg instanceof JCExpression) {
+            JCExpression tree = (JCExpression)arg;
+            s = "@" + tree.getStartPosition();
+        } else if (arg instanceof BaseFileObject) {
             s = ((BaseFileObject) arg).getShortName();
-        else
+        } else {
             s = super.formatArgument(diag, arg, null);
-        if (arg instanceof JCDiagnostic)
-            return "(" + s + ")";
-        else
-            return s;
+        }
+        return (arg instanceof JCDiagnostic) ? "(" + s + ")" : s;
     }
 
     @Override
--- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -393,11 +393,6 @@
         }
 
         @Override
-        protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
-            return super.printMethodArgs(args, varArgs, locale);
-        }
-
-        @Override
         public String visitClassSymbol(ClassSymbol s, Locale locale) {
             String name = nameSimplifier.simplify(s);
             if (name.length() == 0 ||
--- a/langtools/src/share/classes/com/sun/tools/javac/util/SharedNameTable.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/SharedNameTable.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -93,13 +93,7 @@
     @Override
     public Name fromChars(char[] cs, int start, int len) {
         int nc = this.nc;
-        byte[] bytes = this.bytes;
-        while (nc + len * 3 >= bytes.length) {
-            //          System.err.println("doubling name buffer of length " + names.length + " to fit " + len + " chars");//DEBUG
-            byte[] newnames = new byte[bytes.length * 2];
-            System.arraycopy(bytes, 0, newnames, 0, bytes.length);
-            bytes = this.bytes = newnames;
-        }
+        byte[] bytes = this.bytes = ArrayUtils.ensureCapacity(this.bytes, nc + len * 3);
         int nbytes = Convert.chars2utf(cs, start, bytes, nc, len) - nc;
         int h = hashValue(bytes, nc, nbytes) & hashMask;
         NameImpl n = hashes[h];
@@ -133,12 +127,7 @@
         }
         if (n == null) {
             int nc = this.nc;
-            while (nc + len > names.length) {
-                //              System.err.println("doubling name buffer of length + " + names.length + " to fit " + len + " bytes");//DEBUG
-                byte[] newnames = new byte[names.length * 2];
-                System.arraycopy(names, 0, newnames, 0, names.length);
-                names = this.bytes = newnames;
-            }
+            names = this.bytes = ArrayUtils.ensureCapacity(names, nc + len);
             System.arraycopy(cs, start, names, nc, len);
             n = new NameImpl(this);
             n.index = nc;
--- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2012, 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
@@ -45,8 +45,8 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-class CodeWriter extends BasicWriter {
-    static CodeWriter instance(Context context) {
+public class CodeWriter extends BasicWriter {
+    public static CodeWriter instance(Context context) {
         CodeWriter instance = context.get(CodeWriter.class);
         if (instance == null)
             instance = new CodeWriter(context);
--- a/langtools/src/share/classes/com/sun/tools/javap/StackMapWriter.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javap/StackMapWriter.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, 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,10 +25,11 @@
 
 package com.sun.tools.javap;
 
-import com.sun.tools.classfile.AccessFlags;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.Attribute;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.ConstantPool;
@@ -233,8 +234,7 @@
             StackMap prev = map.get(pc);
             assert (prev != null);
             int k = 251 - frame.frame_type;
-            verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
-            System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
+            verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);
             StackMap m = new StackMap(new_locals, empty);
             map.put(new_pc, m);
             return new_pc;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testHelpFile/TestHelpFile.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 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
+ * @bug      7132631
+ * @summary  Make sure that the help file is generated correctly.
+ * @author   Bhavesh Patel
+ * @library  ../lib/
+ * @build    JavadocTester TestHelpFile
+ * @run main TestHelpFile
+ */
+
+public class TestHelpFile extends JavadocTester {
+
+    //Test information.
+    private static final String BUG_ID = "7132631";
+
+    //Javadoc arguments.
+    private static final String[] ARGS = new String[] {
+        "-d", BUG_ID, "-sourcepath", SRC_DIR,
+            SRC_DIR + FS + "TestHelpFile.java"
+    };
+
+    private static final String[][] NEGATED_TEST = NO_TEST;
+
+    private static final String[][] TEST = {
+        {BUG_ID + FS + "help-doc.html",
+            "<a href=\"constant-values.html\">Constant Field Values</a>"
+        },
+    };
+
+    /**
+     * The entry point of the test.
+     * @param args the array of command line arguments.
+     */
+    public static void main(String[] args) {
+        TestHelpFile tester = new TestHelpFile();
+        run(tester, ARGS, TEST, NEGATED_TEST);
+        tester.printSummary();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugId() {
+        return BUG_ID;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getBugName() {
+        return getClass().getName();
+    }
+}
--- a/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java	Thu Oct 11 17:00:54 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4496290 4985072 7006178
+ * @bug 4496290 4985072 7006178 7068595
  * @summary A simple test to determine if -use works.
  * @author jamieh
  * @library ../lib/
@@ -34,7 +34,7 @@
 
 public class TestUseOption extends JavadocTester {
 
-    private static final String BUG_ID = "4496290-4985072-7006178";
+    private static final String BUG_ID = "4496290-4985072-7006178-7068595";
 
     //Input for string search tests.
     private static final String[] TEST2 = {
@@ -64,6 +64,13 @@
         }
     };
 
+    private static final String[][] TEST4 = {
+        {BUG_ID + "-4" + FS + "pkg2" + FS + "class-use" + FS + "C3.html", "<a href=" +
+                 "\"../../index.html?pkg2/class-use/C3.html\" target=\"_top\">" +
+                 "Frames</a></li>"
+        }
+    };
+
     private static final String[] ARGS = new String[] {
         "-d", BUG_ID, "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
     };
@@ -76,6 +83,10 @@
         "-d", BUG_ID + "-3", "-sourcepath", SRC_DIR, "-use", SRC_DIR + FS + "C.java", SRC_DIR + FS + "UsedInC.java"
     };
 
+    private static final String[] ARGS4 = new String[] {
+        "-d", BUG_ID + "-4", "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
+    };
+
     /**
      * The entry point of the test.
      * @param args the array of command line arguments.
@@ -108,6 +119,7 @@
         }
         tester.printSummary();
         run(tester, ARGS3, TEST3, NO_TEST);
+        run(tester, ARGS4, TEST4, NO_TEST);
         tester.printSummary();
     }
 
--- a/langtools/test/tools/javac/6402516/TestLocalElements.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/6402516/TestLocalElements.java	Thu Oct 11 17:00:54 2012 -0700
@@ -43,9 +43,9 @@
 
     boolean b = new Object() {
             public boolean equals(Object other) {
-                String p = "p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
-                String q = "q, p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
-                String r = "r, q, p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
+                String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
+                String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
+                String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
                 return (this == other);
             }
 
--- a/langtools/test/tools/javac/6758789/T6758789a.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/6758789/T6758789a.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,3 @@
-T6758789a.java:14:9: compiler.err.cant.apply.symbol.1: kindname.method, m1, compiler.misc.no.args, int, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
-T6758789a.java:15:9: compiler.err.cant.apply.symbol.1: kindname.method, m2, int, compiler.misc.no.args, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
+T6758789a.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m1, compiler.misc.no.args, int, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
+T6758789a.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m2, int, compiler.misc.no.args, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
 2 errors
--- a/langtools/test/tools/javac/6758789/T6758789b.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/6758789/T6758789b.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,4 +1,4 @@
-T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
+T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<X>
 T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
 - compiler.err.warnings.and.werror
 1 error
--- a/langtools/test/tools/javac/6840059/T6840059.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/6840059/T6840059.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,2 @@
-T6840059.java:15:9: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
-T6840059.java:15:25: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, compiler.misc.no.args, kindname.class, T6840059, (compiler.misc.arg.length.mismatch)
-2 errors
+T6840059.java:15:9: compiler.err.cant.apply.symbol: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
+1 error
--- a/langtools/test/tools/javac/6857948/T6857948.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/6857948/T6857948.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,2 @@
 T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , (compiler.misc.location: kindname.class, Test, null)
-T6857948.java:16:50: compiler.err.cant.apply.symbol.1: kindname.constructor, Foo, java.lang.String, compiler.misc.no.args, kindname.class, Foo, (compiler.misc.arg.length.mismatch)
-2 errors
+1 error
--- a/langtools/test/tools/javac/7132880/T7132880.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/7132880/T7132880.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,4 +1,4 @@
-T7132880.java:23:12: compiler.err.cant.apply.symbol.1: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
+T7132880.java:23:12: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
 T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Double))),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)))}
 T7132880.java:43:12: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.lang.Object,int), Outer.Inner3, kindname.method, m2(int,java.lang.Object), Outer.Inner3
 3 errors
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234a_1.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234a_1.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,2 +1,2 @@
-T6722234a.java:12:9: compiler.err.cant.apply.symbol.1: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
+T6722234a.java:12:9: compiler.err.cant.apply.symbol: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
 1 error
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234a_2.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234a_2.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,3 @@
-T6722234a.java:12:9: compiler.err.cant.apply.symbol.1: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
+T6722234a.java:12:9: compiler.err.cant.apply.symbol: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
 - compiler.misc.where.description.typevar.1: compiler.misc.type.var: T, 1,compiler.misc.type.var: T, 2,{(compiler.misc.where.typevar: compiler.misc.type.var: T, 1, java.lang.String, kindname.class, T6722234a),(compiler.misc.where.typevar: compiler.misc.type.var: T, 2, java.lang.Integer, kindname.method, <compiler.misc.type.var: T, 2>test(compiler.misc.type.var: T, 2))}
 1 error
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234b_1.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234b_1.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,2 +1,2 @@
-T6722234b.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, List<T>,List<T>, List<compiler.misc.type.captureof: 1, ? extends T6722234b>,List<compiler.misc.type.captureof: 2, ? extends T6722234b>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ? extends T6722234b, compiler.misc.type.captureof: 2, ? extends T6722234b,compiler.misc.type.captureof: 1, ? extends T6722234b)
+T6722234b.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, List<T>,List<T>, List<compiler.misc.type.captureof: 1, ? extends T6722234b>,List<compiler.misc.type.captureof: 2, ? extends T6722234b>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ? extends T6722234b, compiler.misc.type.captureof: 2, ? extends T6722234b,compiler.misc.type.captureof: 1, ? extends T6722234b)
 1 error
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234b_2.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234b_2.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,4 +1,4 @@
-T6722234b.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, List<T>,List<T>, List<compiler.misc.captured.type: 1>,List<compiler.misc.captured.type: 2>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.captured.type: 2, compiler.misc.captured.type: 2,compiler.misc.captured.type: 1)
+T6722234b.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, List<T>,List<T>, List<compiler.misc.captured.type: 1>,List<compiler.misc.captured.type: 2>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.captured.type: 2, compiler.misc.captured.type: 2,compiler.misc.captured.type: 1)
 - compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, Object, kindname.method, <T>m(List<T>,List<T>))}
 - compiler.misc.where.description.captured.1: compiler.misc.captured.type: 1,compiler.misc.captured.type: 2,{(compiler.misc.where.captured.1: compiler.misc.captured.type: 1, T6722234b, compiler.misc.type.null, ? extends T6722234b),(compiler.misc.where.captured.1: compiler.misc.captured.type: 2, T6722234b, compiler.misc.type.null, ? extends T6722234b)}
 1 error
--- a/langtools/test/tools/javac/Diagnostics/6722234/T6722234c.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6722234/T6722234c.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,2 +1,2 @@
-T6722234c.java:14:9: compiler.err.cant.apply.symbol.1: kindname.method, m, T6722234c.String, java.lang.String, kindname.class, T6722234c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.lang.String, T6722234c.String))
+T6722234c.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, T6722234c.String, java.lang.String, kindname.class, T6722234c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.lang.String, T6722234c.String))
 1 error
--- a/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6862608/T6862608a.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,3 @@
-T6862608a.java:19:33: compiler.err.cant.apply.symbol.1: kindname.method, compound, java.lang.Iterable<? extends java.util.Comparator<? super T>>, java.util.List<java.util.Comparator<?>>, kindname.class, T6862608a, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.List<java.util.Comparator<?>>, java.lang.Iterable<? extends java.util.Comparator<? super T>>))
+T6862608a.java:19:33: compiler.err.cant.apply.symbol: kindname.method, compound, java.lang.Iterable<? extends java.util.Comparator<? super T>>, java.util.List<java.util.Comparator<?>>, kindname.class, T6862608a, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.List<java.util.Comparator<?>>, java.lang.Iterable<? extends java.util.Comparator<? super T>>))
 - 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/langtools/test/tools/javac/Diagnostics/6862608/T6862608b.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/Diagnostics/6862608/T6862608b.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,3 +1,3 @@
-T6862608b.java:11:7: compiler.err.cant.apply.symbol.1: kindname.method, test, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T66862608b<compiler.misc.type.var: T, 1,compiler.misc.type.var: S, 2>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
+T6862608b.java:11:7: compiler.err.cant.apply.symbol: kindname.method, test, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T66862608b<compiler.misc.type.var: T, 1,compiler.misc.type.var: S, 2>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
 - compiler.misc.where.description.typevar.1: compiler.misc.type.var: T, 1,compiler.misc.type.var: T, 2,compiler.misc.type.var: S, 1,compiler.misc.type.var: S, 2,{(compiler.misc.where.typevar: compiler.misc.type.var: T, 1, java.lang.String, kindname.class, T66862608b),(compiler.misc.where.typevar: compiler.misc.type.var: T, 2, compiler.misc.type.var: S, 1, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 1, java.lang.Object, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 2, java.lang.Object, kindname.class, T66862608b)}
 1 error
--- a/langtools/test/tools/javac/T6326754.out	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/T6326754.out	Thu Oct 11 17:00:54 2012 -0700
@@ -1,7 +1,7 @@
 T6326754.java:44:12: compiler.err.name.clash.same.erasure: TestConstructor(T), TestConstructor(K)
 T6326754.java:52:17: compiler.err.name.clash.same.erasure: setT(K), setT(T)
 T6326754.java:64:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T, T)
-T6326754.java:70:11: compiler.err.cant.apply.symbol.1: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC<T>, (compiler.misc.arg.length.mismatch)
+T6326754.java:70:11: compiler.err.cant.apply.symbol: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC<T>, (compiler.misc.arg.length.mismatch)
 - compiler.note.unchecked.filename: T6326754.java
 - compiler.note.unchecked.recompile
 4 errors
--- a/langtools/test/tools/javac/conditional/Conditional.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/conditional/Conditional.java	Thu Oct 11 17:00:54 2012 -0700
@@ -27,6 +27,7 @@
  * @summary Conditional operator applies assignment conversion
  * @author Tim Hanson, BEA
  *
+ * @compile -XDallowPoly Conditional.java
  * @compile/fail Conditional.java
  */
 
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java	Thu Oct 11 17:00:54 2012 -0700
@@ -185,6 +185,8 @@
         "compiler.err.cant.resolve.args.params",
         "compiler.err.cant.resolve.location.args",
         "compiler.err.cant.resolve.location.args.params",
+        "compiler.misc.cant.resolve.location.args",
+        "compiler.misc.cant.resolve.location.args.params",
         // JavaCompiler, reports #errors and #warnings
         "compiler.misc.count.error",
         "compiler.misc.count.error.plural",
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt	Thu Oct 11 09:50:52 2012 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt	Thu Oct 11 17:00:54 2012 -0700
@@ -1,7 +1,6 @@
 compiler.err.already.annotated                          # internal compiler error?
 compiler.err.already.defined.this.unit                  # seems to be masked by compiler.err.duplicate.class
 compiler.err.annotation.value.not.allowable.type        # cannot happen: precluded by complete type-specific tests
-compiler.err.cant.apply.symbol
 compiler.err.cant.read.file                             # (apt.JavaCompiler?)
 compiler.err.cant.select.static.class.from.param.type
 compiler.err.illegal.char.for.encoding
@@ -65,6 +64,7 @@
 compiler.misc.kindname.type.variable
 compiler.misc.kindname.type.variable.bound
 compiler.misc.kindname.value
+compiler.misc.incompatible.eq.lower.bounds              # cannot happen?
 compiler.misc.no.unique.minimal.instance.exists
 compiler.misc.resume.abort                              # prompt for a response
 compiler.misc.source.unavailable                        # DiagnosticSource
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantAccessArgTypeInFunctionalDesc.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 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.cant.access.arg.type.in.functional.desc
+// key: compiler.err.report.access
+// options: -XDallowLambda
+
+interface SAM_InaccessibleArg {
+    void m(Foo.Bar bar);
+    static class Foo { private class Bar { } }
+}
+
+class CantAccessArgTypeInFunctionalDesc {
+    SAM_InaccessibleArg s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantAccessInnerClsConstr.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 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.prob.found.req
+// key: compiler.misc.cant.access.inner.cls.constr
+// key: compiler.misc.invalid.mref
+// options: -XDallowMethodReferences
+
+class CantAccessInnerClsConstructor {
+
+    interface SAM {
+        Outer m();
+    }
+
+    class Outer { }
+
+    static void test() {
+        SAM s = Outer::new;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantAccessReturnTypeInFunctionalDesc.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 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.cant.access.return.in.functional.desc
+// options: -XDallowLambda
+
+interface SAM_InaccessibleRet {
+    Foo.Bar m();
+    static class Foo { private class Bar { } }
+}
+
+class CantAccessReturnTypeInFunctionalDesc {
+    SAM_InaccessibleRet s = ()->null;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantAccessThrownTypesInFunctionalDesc.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 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.cant.access.thrown.in.functional.desc
+// options: -XDallowLambda
+
+interface SAM_InaccessibleThrown {
+    void m() throws Foo.Bar;
+    static class Foo { private class Bar extends Exception { } }
+}
+
+class CantAccessThrownTypesInFunctionalDesc {
+    SAM_InaccessibleThrown s = ()-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantApplySymbolFragment.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 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.prob.found.req
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.no.conforming.assignment.exists
+// key: compiler.misc.cant.apply.symbol
+// key: compiler.misc.invalid.mref
+// options: -XDallowMethodReferences
+
+class CantApplySymbolFragment {
+
+    interface SAM {
+        void m(Integer u);
+    }
+
+    static void f(String s) { }
+
+    void test() {
+        SAM s = CantApplySymbolFragment::f;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantApplySymbolsFragment.java	Thu Oct 11 17:00:54 2012 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR RE