changeset 14058:c7ec7facdd20

7177385: Add attribution support for lambda expressions Summary: Add support for function descriptor lookup, functional interface inference and lambda expression type-checking Reviewed-by: jjg, dlsmith
author mcimadamore
date Fri, 05 Oct 2012 14:35:24 +0100
parents b4b0377b8dba
children 3bee341587fa
files langtools/src/share/classes/com/sun/tools/javac/code/Printer.java langtools/src/share/classes/com/sun/tools/javac/code/Type.java langtools/src/share/classes/com/sun/tools/javac/code/Types.java langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java langtools/src/share/classes/com/sun/tools/javac/comp/Check.java langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java langtools/test/tools/javac/6402516/TestLocalElements.java langtools/test/tools/javac/diags/examples.not-yet.txt langtools/test/tools/javac/diags/examples/CantAccessArgTypeInFunctionalDesc.java langtools/test/tools/javac/diags/examples/CantAccessReturnTypeInFunctionalDesc.java langtools/test/tools/javac/diags/examples/CantAccessThrownTypesInFunctionalDesc.java langtools/test/tools/javac/diags/examples/CantRefNonEffectivelyFinalVar.java langtools/test/tools/javac/diags/examples/CatchWithoutTry.java langtools/test/tools/javac/diags/examples/CyclicInference.java langtools/test/tools/javac/diags/examples/IncompatibleAbstracts.java langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInLambda.java langtools/test/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java langtools/test/tools/javac/diags/examples/IncompatibleRetTypeInLambda.java langtools/test/tools/javac/diags/examples/IncompatibleThrownTypesInLambda.java langtools/test/tools/javac/diags/examples/InvalidGenericDescInFunctionalInterface.java langtools/test/tools/javac/diags/examples/MissingReturnValueFragment.java langtools/test/tools/javac/diags/examples/NoAbstracts.java langtools/test/tools/javac/diags/examples/NoSuitableFunctionalIntfInst.java langtools/test/tools/javac/diags/examples/NotAFunctionalIntf.java langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java langtools/test/tools/javac/diags/examples/TypeConditional.java langtools/test/tools/javac/diags/examples/UnexpectedLambda.java langtools/test/tools/javac/failover/CheckAttributedTree.java langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out
diffstat 42 files changed, 1878 insertions(+), 220 deletions(-) [+]
line wrap: on
line diff
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Fri Oct 05 14:35:24 2012 +0100
@@ -54,11 +54,8 @@
 
     List<Type> seenCaptured = List.nil();
     static final int PRIME = 997;  // largest prime less than 1000
-    boolean raw;
 
-    protected Printer(boolean raw) {
-        this.raw = raw;
-    }
+    protected Printer() { }
 
     /**
      * This method should be overriden in order to provide proper i18n support.
@@ -87,7 +84,7 @@
      * @return printer visitor instance
      */
     public static Printer createStandardPrinter(final Messages messages) {
-        return new Printer(false) {
+        return new Printer() {
             @Override
             protected String localize(Locale locale, String key, Object... args) {
                 return messages.getLocalizedString(locale, key, args);
@@ -174,34 +171,6 @@
         return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
     }
 
-    public String visitDeferredType(DeferredType t, Locale locale) {
-        return raw ? localize(locale, getDeferredKey(t.tree)) :
-            deferredTypeTree2String(t.tree);
-    }
-    //where
-        private String deferredTypeTree2String(JCTree tree) {
-            switch(tree.getTag()) {
-                case PARENS:
-                    return deferredTypeTree2String(((JCTree.JCParens)tree).expr);
-                case CONDEXPR:
-                    return Pretty.toSimpleString(tree, 15);
-                default:
-                    Assert.error("unexpected tree kind " + tree.getKind());
-                    return null;
-            }
-        }
-        private String getDeferredKey (JCTree tree) {
-            switch (tree.getTag()) {
-                case PARENS:
-                    return getDeferredKey(((JCTree.JCParens)tree).expr);
-                case CONDEXPR:
-                     return "compiler.misc.type.conditional";
-                default:
-                    Assert.error("unexpected tree kind " + tree.getKind());
-                    return null;
-            }
-        }
-
     @Override
     public String visitUndetVar(UndetVar t, Locale locale) {
         if (t.inst != null) {
@@ -265,14 +234,10 @@
     }
 
     public String visitType(Type t, Locale locale) {
-        if (t.tag == DEFERRED) {
-            return visitDeferredType((DeferredType)t, locale);
-        } else {
-            String s = (t.tsym == null || t.tsym.name == null)
-                    ? localize(locale, "compiler.misc.type.none")
-                    : t.tsym.name.toString();
-            return s;
-        }
+        String s = (t.tsym == null || t.tsym.name == null)
+                ? localize(locale, "compiler.misc.type.none")
+                : t.tsym.name.toString();
+        return s;
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Fri Oct 05 14:35:24 2012 +0100
@@ -1220,9 +1220,13 @@
         }
 
         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, types.getBounds(origin));
+            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());
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Fri Oct 05 14:35:24 2012 +0100
@@ -79,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) {
@@ -102,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>
 
@@ -296,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?
@@ -1215,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) {
@@ -2007,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 {
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Oct 05 14:35:24 2012 +0100
@@ -43,6 +43,7 @@
 import com.sun.tools.javac.comp.Check.CheckContext;
 
 import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.LambdaExpressionTree;
 import com.sun.source.tree.MemberSelectTree;
 import com.sun.source.tree.TreeVisitor;
 import com.sun.source.util.SimpleTreeVisitor;
@@ -85,6 +86,7 @@
     final Infer infer;
     final DeferredAttr deferredAttr;
     final Check chk;
+    final Flow flow;
     final MemberEnter memberEnter;
     final TreeMaker make;
     final ConstFold cfolder;
@@ -110,6 +112,7 @@
         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);
@@ -133,17 +136,20 @@
         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.
@@ -174,6 +180,10 @@
      */
     boolean allowCovariantReturns;
 
+    /** Switch: support lambda expressions ?
+     */
+    boolean allowLambda;
+
     /** Switch: allow references to surrounding object from anonymous
      * objects during constructor call?
      */
@@ -196,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;
@@ -286,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;
@@ -505,10 +524,36 @@
         }
     }
 
+    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;
@@ -987,7 +1032,9 @@
             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)) {
                     // In this case, `v' is final.  Ensure that it's initializer is
                     // evaluated.
                     v.getConstValue(); // ensure initializer is evaluated
@@ -1501,37 +1548,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;
             }
@@ -1961,6 +2009,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
@@ -2016,6 +2066,32 @@
             }
         }
 
+            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");
+                    }
+                }
+            }
+
     /** Make an attributed null check tree.
      */
     public JCExpression makeNullCheck(JCExpression arg) {
@@ -2064,15 +2140,222 @@
         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);
+            }
+        }
     }
-
-    @Override
-    public void visitReference(JCMemberReference that) {
-        throw new UnsupportedOperationException("Member references not supported yet");
-    }
+    //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;
+        }
 
     public void visitParens(JCParens tree) {
         Type owntype = attribTree(tree.expr, env, resultInfo);
@@ -3355,8 +3638,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 {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Oct 05 14:35:24 2012 +0100
@@ -421,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
          */
@@ -438,6 +438,8 @@
         public Infer.InferenceContext inferenceContext();
 
         public DeferredAttr.DeferredAttrContext deferredAttrContext();
+
+        public boolean allowBoxing();
     }
 
     /**
@@ -472,6 +474,10 @@
         public DeferredAttrContext deferredAttrContext() {
             return enclosingContext.deferredAttrContext();
         }
+
+        public boolean allowBoxing() {
+            return enclosingContext.allowBoxing();
+        }
     }
 
     /**
@@ -496,6 +502,10 @@
         public DeferredAttrContext deferredAttrContext() {
             return deferredAttr.emptyDeferredAttrContext;
         }
+
+        public boolean allowBoxing() {
+            return true;
+        }
     };
 
     /** Check that a given type is assignable to a given proto-type.
@@ -557,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);
         }
@@ -906,6 +916,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)
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Oct 05 14:35:24 2012 +0100
@@ -497,7 +497,7 @@
          * a default expected type (j.l.Object).
          */
         private Type recover(DeferredType dt) {
-            dt.check(new RecoveryInfo());
+            dt.check(attr.new RecoveryInfo(deferredAttrContext));
             switch (TreeInfo.skipParens(dt.tree).getTag()) {
                 case LAMBDA:
                 case REFERENCE:
@@ -509,31 +509,6 @@
                     return super.apply(dt);
             }
         }
-
-        class RecoveryInfo extends ResultInfo {
-
-            public RecoveryInfo() {
-                attr.super(Kinds.VAL, Type.recoveryType, new Check.NestedCheckContext(chk.basicHandler) {
-                    @Override
-                    public 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));
-            }
-        }
     }
 
     /**
@@ -541,13 +516,125 @@
      * an AST node can be type-checked
      */
     @SuppressWarnings("fallthrough")
-    List<Type> stuckVars(JCExpression tree, ResultInfo resultInfo) {
-        switch (tree.getTag()) {
-            case LAMBDA:
-            case REFERENCE:
-                Assert.error("not supported yet");
-            default:
-                return List.nil();
+    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 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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 ----------------------*/
@@ -1552,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);
@@ -1596,6 +1671,7 @@
                 uninits = uninitsPrev;
                 nextadr = nextadrPrev;
                 firstadr = firstadrPrev;
+                returnadr = returnadrPrev;
                 lint = lintPrev;
             }
         }
@@ -1980,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 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Oct 05 14:35:24 2012 +0100
@@ -274,7 +274,7 @@
                                   Resolve.MethodResolutionContext resolveContext,
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
-        final InferenceContext inferenceContext = new InferenceContext(tvars, this);
+        final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
         inferenceException.clear();
 
         try {
@@ -467,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
@@ -536,9 +605,17 @@
      * Mapping that turns inference variables into undet vars
      * (used by inference context)
      */
-    Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
+    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);
+            if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types, includeBounds);
             else return t.map(this);
         }
     };
@@ -573,8 +650,8 @@
 
         List<FreeTypeListener> freetypeListeners = List.nil();
 
-        public InferenceContext(List<Type> inferencevars, Infer infer) {
-            this.undetvars = Type.map(inferencevars, infer.fromTypeVarFun);
+        public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) {
+            this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds));
             this.inferencevars = inferencevars;
         }
 
@@ -737,5 +814,5 @@
         }
     }
 
-    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this);
+    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false);
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Fri Oct 05 14:35:24 2012 +0100
@@ -646,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);
@@ -671,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 ||
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Oct 05 14:35:24 2012 +0100
@@ -753,6 +753,10 @@
         public boolean compatible(Type found, Type req, Warner warn) {
             return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
         }
+
+        public boolean allowBoxing() {
+            return false;
+        }
     }
 
     /**
@@ -769,6 +773,10 @@
         public boolean compatible(Type found, Type req, Warner warn) {
             return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
         }
+
+        public boolean allowBoxing() {
+            return true;
+        }
     }
 
     /**
@@ -1036,7 +1044,7 @@
         }
         return (bestSoFar.kind > AMBIGUOUS)
             ? sym
-            : mostSpecific(sym, bestSoFar, env, site,
+            : mostSpecific(argtypes, sym, bestSoFar, env, site,
                            allowBoxing && operator, useVarargs);
     }
 
@@ -1050,7 +1058,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,
@@ -1059,8 +1067,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);
@@ -1127,8 +1137,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 &&
@@ -1142,13 +1152,82 @@
         }
     }
     //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);
+
+            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
@@ -1187,6 +1266,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();
@@ -2388,7 +2493,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;
+        }
     }
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Oct 05 14:35:24 2012 +0100
@@ -627,6 +627,11 @@
         result = tree;
     }
 
+    @Override
+    public void visitLambda(JCLambda tree) {
+        Assert.error("Translation of lambda expression 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/main/JavaCompiler.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Oct 05 14:35:24 2012 +0100
@@ -1227,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);
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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();
@@ -1343,11 +1344,6 @@
     }
 
     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
-        if (token.kind != ARROW) {
-            //better error recovery
-            return F.at(pos).Erroneous(args);
-        }
-
         checkLambda();
         accept(ARROW);
 
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Oct 05 14:35:24 2012 +0100
@@ -164,6 +164,54 @@
 compiler.err.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
 compiler.err.cant.assign.val.to.final.var=\
     cannot assign a value to final variable {0}
@@ -173,6 +221,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
 
@@ -592,6 +643,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
 
@@ -639,6 +693,18 @@
 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: list of type
+compiler.err.incompatible.thrown.types.in.lambda=\
+    incompatible thrown types {0} in lambda expression
+
+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
 
@@ -995,6 +1061,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
 
@@ -1755,6 +1825,9 @@
     required: {0}\n\
     found:    {1}
 
+compiler.err.unexpected.lambda=\
+   lambda expression 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)
@@ -2094,9 +2167,6 @@
 compiler.misc.type.null=\
     <null>
 
-compiler.misc.type.conditional=\
-    conditional expression
-
 # X#n (where n is an int id) is disambiguated tvar name
 # 0: name, 1: number
 compiler.misc.type.var=\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java	Fri Oct 05 14:35:24 2012 +0100
@@ -87,6 +87,11 @@
      */
     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 {
@@ -135,6 +140,10 @@
         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 {
@@ -938,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 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Fri Oct 05 14:35:24 2012 +0100
@@ -262,6 +262,10 @@
         }
     }
 
+    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
      */
@@ -400,6 +404,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 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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,19 @@
             return String.valueOf(arg);
         }
     }
+    //where
+            private String expr2String(JCExpression tree) {
+                switch(tree.getTag()) {
+                    case PARENS:
+                        return expr2String(((JCParens)tree).expr);
+                    case LAMBDA:
+                    case CONDEXPR:
+                        return Pretty.toSimpleString(tree);
+                    default:
+                        Assert.error("unexpected tree kind " + tree.getKind());
+                        return null;
+                }
+            }
 
     /**
      * Format an iterable argument of a given diagnostic.
@@ -489,7 +507,7 @@
      * type referred by a given captured type C contains C itself) which might
      * lead to infinite loops.
      */
-    protected Printer printer = new Printer(isRaw()) {
+    protected Printer printer = new Printer() {
 
         @Override
         protected String localize(Locale locale, String key, Object... args) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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 04 13:04:53 2012 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java	Fri Oct 05 14:35:24 2012 +0100
@@ -325,10 +325,6 @@
      */
     protected class RichPrinter extends Printer {
 
-        public RichPrinter() {
-            super(formatter.isRaw());
-        }
-
         @Override
         public String localize(Locale locale, String key, Object... args) {
             return formatter.localize(locale, key, args);
--- a/langtools/test/tools/javac/6402516/TestLocalElements.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/6402516/TestLocalElements.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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/diags/examples.not-yet.txt	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt	Fri Oct 05 14:35:24 2012 +0100
@@ -58,7 +58,6 @@
 compiler.misc.fatal.err.cant.close	                # JavaCompiler
 compiler.misc.file.does.not.contain.package
 compiler.misc.illegal.start.of.class.file
-compiler.misc.cyclic.inference                          # Cannot happen w/o lambdas
 compiler.misc.kindname.annotation
 compiler.misc.kindname.enum
 compiler.misc.kindname.package
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantAccessArgTypeInFunctionalDesc.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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/CantAccessReturnTypeInFunctionalDesc.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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	Fri Oct 05 14:35:24 2012 +0100
@@ -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 = ()-> { };
+}
--- a/langtools/test/tools/javac/diags/examples/CantRefNonEffectivelyFinalVar.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/diags/examples/CantRefNonEffectivelyFinalVar.java	Fri Oct 05 14:35:24 2012 +0100
@@ -23,7 +23,8 @@
 
 // key: compiler.err.cant.ref.non.effectively.final.var
 // key: compiler.misc.inner.cls
-// options: -XDallowEffectivelyFinalInInnerClasses
+// key: compiler.misc.lambda
+// options: -XDallowLambda -XDallowEffectivelyFinalInInnerClasses
 
 class CantRefNonEffectivelyFinalVar {
     void test() {
@@ -31,4 +32,14 @@
         new Object() { int j = i; };
         i = 2;
     }
+
+    interface SAM {
+        void m();
+    }
+
+    void test2() {
+        int i = 0;
+        SAM s = ()-> { int j = i; };
+        i++;
+    }
 }
--- a/langtools/test/tools/javac/diags/examples/CatchWithoutTry.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/diags/examples/CatchWithoutTry.java	Fri Oct 05 14:35:24 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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,6 +23,8 @@
 
 // key: compiler.err.catch.without.try
 // key: compiler.err.expected
+// key: compiler.err.not.stmt
+// key: compiler.err.lambda.not.supported.in.source
 
 class CatchWithoutTry {
     void m() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CyclicInference.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,38 @@
+/*
+ * 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.apply.symbol.1
+// key: compiler.misc.cyclic.inference
+// options: -XDallowLambda -XDallowPoly
+
+class CyclicInference {
+    interface SAM<X> {
+        void m(X x);
+    }
+
+    <Z> void g(SAM<Z> sz) { }
+
+    void test() {
+        g(x-> {});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IncompatibleAbstracts.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,37 @@
+/*
+ * 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.not.a.functional.intf.1
+// key: compiler.misc.incompatible.abstracts
+// options: -XDallowLambda
+
+class IncompatibleAbstracts {
+
+    interface SAM {
+        void m(String s);
+        void m(Integer i);
+    }
+
+    SAM s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInLambda.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.incompatible.arg.types.in.lambda
+// options: -XDallowLambda -XDallowPoly
+
+class IncompatibleArgTypesInLambda {
+    interface SAM {
+        void m(Integer x);
+    }
+
+    SAM s = (String x)-> {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IncompatibleDescsInFunctionalIntf.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,43 @@
+/*
+ * 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.types.incompatible.diff.ret
+// key: compiler.err.prob.found.req
+// key: compiler.misc.incompatible.descs.in.functional.intf
+// key: compiler.misc.descriptor
+// key: compiler.misc.descriptor.throws
+// options: -XDallowLambda
+
+class IncompatibleDescsInFunctionalIntf {
+    interface A {
+        Integer m(String i) throws Exception;
+    }
+
+    interface B {
+        String m(String i);
+    }
+
+    interface SAM extends A,B { }
+
+    SAM s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IncompatibleRetTypeInLambda.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.incompatible.ret.type.in.lambda
+// options: -XDallowLambda -XDallowPoly
+
+class IncompatibleRetTypeInLambda {
+    interface SAM {
+        Integer m();
+    }
+
+    SAM s = ()-> "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IncompatibleThrownTypesInLambda.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,33 @@
+/*
+ * 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.incompatible.thrown.types.in.lambda
+// options: -XDallowLambda
+
+class IncompatibleThrownTypesInLambda {
+    interface SAM {
+        void m();
+    }
+
+    SAM s = ()-> { throw new Exception(); };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/InvalidGenericDescInFunctionalInterface.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.invalid.generic.desc.in.functional.intf
+// options: -XDallowLambda
+
+class InvalidGenericDescInFunctionalIntf {
+
+    interface SAM {
+        <Z> void m();
+    }
+
+    SAM s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/MissingReturnValueFragment.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,37 @@
+/*
+ * 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.incompatible.ret.type.in.lambda
+// key: compiler.misc.missing.ret.val
+// options: -XDallowLambda
+
+class MissingReturnValueFragment {
+    interface SAM {
+        String m();
+    }
+
+    void test() {
+        SAM s = ()->{};
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NoAbstracts.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.not.a.functional.intf.1
+// key: compiler.misc.no.abstracts
+// options: -XDallowLambda
+
+class NoAbstracts {
+
+    interface SAM { }
+
+    SAM s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NoSuitableFunctionalIntfInst.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.no.suitable.functional.intf.inst
+// options: -XDallowLambda
+
+class NoSuitableFunctionalIntfInst {
+
+    interface SAM<X extends Number> {
+        void m(X x);
+    }
+
+    SAM<?> ss = (String s)-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotAFunctionalIntf.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.prob.found.req
+// key: compiler.misc.not.a.functional.intf
+// options: -XDallowLambda
+
+class NotAFunctionalIntf {
+
+    abstract class SAM {
+        abstract <Z> void m();
+    }
+
+    SAM s = x-> { };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java	Fri Oct 05 14:35:24 2012 +0100
@@ -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.note.potential.lambda.found
+// options: -XDallowLambda -XDidentifyLambdaCandidate=true
+
+class PotentialLambdaFound {
+
+    interface SAM {
+        void m();
+    }
+
+    SAM s = new SAM() { public void m() { } };
+}
--- a/langtools/test/tools/javac/diags/examples/TypeConditional.java	Thu Oct 04 13:04:53 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * 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.apply.symbol.1
-// key: compiler.misc.type.conditional
-// key: compiler.misc.no.args
-// key: compiler.misc.arg.length.mismatch
-// options: -XDallowPoly
-// run: simple
-
-class TypeConditional {
-
-    void m() { }
-
-    void test() {
-        m(true ? 1 : 2);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnexpectedLambda.java	Fri Oct 05 14:35:24 2012 +0100
@@ -0,0 +1,29 @@
+/*
+ * 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.unexpected.lambda
+// options: -XDallowLambda
+
+class UnexpectedLambda {
+    { (()-> { })++; }
+}
--- a/langtools/test/tools/javac/failover/CheckAttributedTree.java	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/failover/CheckAttributedTree.java	Fri Oct 05 14:35:24 2012 +0100
@@ -376,7 +376,7 @@
                     that.hasTag(CLASSDEF);
         }
 
-        private final List<String> excludedFields = Arrays.asList("varargsElement");
+        private final List<String> excludedFields = Arrays.asList("varargsElement", "targetType");
 
         void check(boolean ok, String label, Info self) {
             if (!ok) {
--- a/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out	Thu Oct 04 13:04:53 2012 +0100
+++ b/langtools/test/tools/javac/typeAnnotations/newlocations/BasicTest.out	Fri Oct 05 14:35:24 2012 +0100
@@ -9,13 +9,9 @@
 BasicTest.java:52:22: compiler.err.illegal.start.of.expr
 BasicTest.java:52:31: compiler.err.expected: ';'
 BasicTest.java:52:37: compiler.err.expected: token.identifier
-BasicTest.java:53:21: compiler.err.illegal.start.of.expr
-BasicTest.java:53:23: compiler.err.expected: ';'
 BasicTest.java:53:30: compiler.err.expected: token.identifier
-BasicTest.java:53:32: compiler.err.illegal.start.of.type
-BasicTest.java:53:37: compiler.err.expected: token.identifier
-BasicTest.java:53:38: compiler.err.expected: ';'
-BasicTest.java:56:17: compiler.err.expected: token.identifier
+BasicTest.java:53:32: compiler.err.lambda.not.supported.in.source: 1.8
+BasicTest.java:53:31: compiler.err.expected: ->
 BasicTest.java:56:23: compiler.err.expected: token.identifier
 BasicTest.java:56:24: compiler.err.expected2: '(', '['
 BasicTest.java:56:25: compiler.err.expected: ';'
@@ -63,4 +59,4 @@
 BasicTest.java:74:25: compiler.err.illegal.start.of.type
 BasicTest.java:74:33: compiler.err.expected: ';'
 BasicTest.java:77:2: compiler.err.premature.eof
-65 errors
+61 errors