changeset 1450:ebb4ad86a284

Enhancement: Maintain a cache of speculatively attributed types. This avoids unnecessary duplicate type-checking steps and allows for better error message reporting (as the types reported on the diagnostics are exactly the types that were computed during a speculative step).
author mcimadamore
date Thu, 09 Aug 2012 18:18:44 +0100
parents 8b3093bc9f0d
children 03bdded4112f
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/GraphInfer.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java test/tools/javac/lambda/TargetType20.out
diffstat 8 files changed, 397 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Aug 09 18:18:44 2012 +0100
@@ -30,8 +30,9 @@
 import javax.lang.model.element.ElementKind;
 import javax.tools.JavaFileObject;
 
-import com.sun.tools.javac.comp.Infer.InferenceContext.PendingCheck;
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.util.*;
@@ -243,15 +244,16 @@
      *  @param resultInfo  The expected result of the tree
      */
     Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) {
-        final Infer.InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();        
+        final InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();        
         Type owntype = found;
         if (owntype.tag != ERROR && resultInfo.pt.tag != METHOD && resultInfo.pt.tag != FORALL) {
             if (inferenceContext.free(found)) {
-                inferenceContext.addPendingCheck(new PendingCheck() {
-                    public void eval() {
+                inferenceContext.addFreeTypeListener(new FreeTypeListener(found) {
+                    @Override
+                    void typeInferred(Type inferredType) {
                         ResultInfo pendingResult =
-                                resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
-                        check(tree, inferenceContext.asInstType(found, types), ownkind, pendingResult);
+                                    resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
+                        check(tree, inferredType, ownkind, pendingResult);
                     }
                 });
                 return tree.type = resultInfo.pt;
@@ -2307,11 +2309,12 @@
         }
     }
     //where
-        private void checkAccessibleSAM(final DiagnosticPosition pos, final Env<AttrContext> env, final Infer.InferenceContext inferenceContext, final Type target) {
+        private void checkAccessibleSAM(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final Type target) {
             if (inferenceContext.free(target)) {
-                inferenceContext.addPendingCheck(new PendingCheck() {
-                    public void eval() {
-                        checkAccessibleSAM(pos, env, inferenceContext, inferenceContext.asInstType(target, types));
+                inferenceContext.addFreeTypeListener(new FreeTypeListener(target) {
+                    @Override
+                    void typeInferred(Type inferredType) {
+                        checkAccessibleSAM(pos, env, inferenceContext, inferredType);
                     }
                 });
             } else {
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Aug 09 18:18:44 2012 +0100
@@ -41,7 +41,7 @@
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.comp.Infer.InferenceContext;
-import com.sun.tools.javac.comp.Infer.InferenceContext.PendingCheck;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.ANNOTATION;
@@ -68,6 +68,7 @@
     private final Resolve rs;
     private final Symtab syms;
     private final Enter enter;
+    private final DeferredAttr deferredAttr;
     private final Infer infer;
     private final Types types;
     private final JCDiagnostic.Factory diags;
@@ -101,6 +102,7 @@
         rs = Resolve.instance(context);
         syms = Symtab.instance(context);
         enter = Enter.instance(context);
+        deferredAttr = DeferredAttr.instance(context);
         infer = InferFactory.instance(context).getInfer();
         this.types = Types.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
@@ -520,9 +522,10 @@
     Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
         final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
         if (inferenceContext.free(req)) {
-            inferenceContext.addPendingCheck(new PendingCheck() {
-                public void eval() {
-                    checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
+            inferenceContext.addFreeTypeListener(new FreeTypeListener(req) {                
+                @Override
+                void typeInferred(Type inferredType) {
+                    checkType(pos, found, inferredType, checkContext);
                 }
             });
         }
@@ -895,7 +898,7 @@
                     kindName(sym),
                     sym.name,
                     rs.methodArguments(sym.type.getParameterTypes()),
-                    rs.methodArguments(Type.map(argtypes, rs.deferredCompleter)),
+                    rs.methodArguments(deferredAttr.attribDeferred(argtypes, DeferredAttr.AttrMode.CHECK, sym, null)),
                     kindName(sym.location()),
                     sym.location());
            owntype = new MethodType(owntype.getParameterTypes(),
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Aug 09 18:18:44 2012 +0100
@@ -41,7 +41,10 @@
 import java.util.Set;
 
 import static com.sun.tools.javac.code.TypeTags.*;
+import com.sun.tools.javac.comp.Infer.InferenceContext;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
+import java.util.HashMap;
+import java.util.Map;
 
 /** 
  * This is an helper class that is used to perform deferred type-analysis.
@@ -94,12 +97,36 @@
 
         public T tree;
         Env<AttrContext> env;
+        Map<Symbol, List<SpeculativeAttrContext>> speculativeContexts =
+                    new HashMap<Symbol, List<SpeculativeAttrContext>>();
 
         DeferredType(T tree, Env<AttrContext> env) {
             super(DEFERRED, Type.noType);
             this.tree = tree;
             this.env = env.dup(tree, env.info.dup());
         }
+        
+        Type getType(Symbol msym, Resolve.MethodResolutionPhase phase) {
+            List<SpeculativeAttrContext> speculativeContextList =
+                    speculativeContexts.get(msym);
+            if (speculativeContextList == null) return null;
+            for (SpeculativeAttrContext sc : speculativeContextList) {
+                if (sc.phase == phase) {
+                    return sc.tree.type;
+                }
+            }
+            return null;
+        }
+        
+        void addContext(Symbol msym, SpeculativeAttrContext newContext) {
+            List<SpeculativeAttrContext> speculativeContextList =
+                    speculativeContexts.get(msym);
+            if (speculativeContextList == null) {
+                speculativeContextList = List.nil();
+                speculativeContexts.put(msym, speculativeContextList);
+            }
+            speculativeContexts.put(msym, speculativeContextList.prepend(newContext));
+        }
     }
     
     /**
@@ -152,67 +179,106 @@
             this.mode = mode;
         }
         
-        abstract Type doAttr(DeferredType<?> dt, ResultInfo result);
+        abstract Type doAttr(DeferredType<?> dt, Symbol msym, Resolve.MethodResolutionPhase phase, ResultInfo result);
         
         boolean accept(AttrMode mode) {
             return mode == this.mode;
         }
     }
     
+    class SpeculativeAttrContext {
+        JCTree tree;
+        Resolve.MethodResolutionPhase phase;
+        ResultInfo resultInfo;
+
+        public SpeculativeAttrContext(JCTree tree, Resolve.MethodResolutionPhase phase, ResultInfo resultInfo) {
+            this.tree = tree;
+            this.phase = phase;
+            this.resultInfo = resultInfo;
+        }
+        
+        void undo() {
+            TreeScanner unenterScanner = new TreeScanner() {
+                @Override
+                public void visitClassDef(JCClassDecl tree) {
+                    ClassSymbol csym = tree.sym;
+                    enter.typeEnvs.remove(csym);
+                    chk.compiled.remove(csym.flatname);
+                    syms.classes.remove(csym.flatname);
+                    super.visitClassDef(tree);
+                }
+            };
+            unenterScanner.scan(tree);
+        }
+    }
+    
     /** array of deferred attribution modes */
     AttrRound[] attrRounds = {    
         new AttrRound(AttrMode.CHECK) {
-            public Type doAttr(final DeferredType<?> dt, ResultInfo result) {
-                List<Type> stuckVars = stuckVars(dt, result);
-                if (stuckVars.nonEmpty()) {
-                    throw new StuckDeferredAttrException(stuckVars);
-                }                
-                Type owntype = attr.attribTree(dt.tree, dt.env, result);
-                //the computed type might contain free variables
-                //which means the type should be recomputed after inference
-                //has completed
-                if (result.checkContext.inferenceContext().free(owntype)) {
-                    final Infer.InferenceContext inferenceContext = result.checkContext.inferenceContext();
-                    result.checkContext.inferenceContext().addPendingCheck(new Infer.InferenceContext.PendingCheck() {
-                        public void eval() {
-                            dt.qtype = inferenceContext.asInstType(dt.qtype, types);
-                        }
-                    });
+            public Type doAttr(final DeferredType<?> dt, Symbol msym, Resolve.MethodResolutionPhase phase, ResultInfo result) {                
+                if (dt.qtype.tag == NONE) {
+                    Assert.check(result.pt.tag != NONE);
+                    List<Type> stuckVars = stuckVars(dt, result);
+                    if (stuckVars.nonEmpty()) {
+                        throw new StuckDeferredAttrException(stuckVars);
+                    }
+                    Type owntype = attr.attribTree(dt.tree, dt.env, result);
+                    //the computed type might contain free variables
+                    //which means the type should be recomputed after inference
+                    //has completed
+                    if (result.checkContext.inferenceContext().free(owntype)) {
+                        result.checkContext.inferenceContext().addFreeTypeListener(new Infer.InferenceContext.FreeTypeListener(owntype) {
+                            @Override
+                            void typeInferred(Type inferredType) {
+                                dt.qtype = inferredType;
+                            }
+                        });
+                    }
+                    dt.qtype = owntype;
                 }
-                return dt.qtype = owntype;
+                return dt.qtype;
             }
         },
         new AttrRound(AttrMode.SPECULATIVE) {
-            public Type doAttr(DeferredType<?> dt, ResultInfo result) {
-                List<Type> stuckVars = stuckVars(dt, result);
-                if (stuckVars.nonEmpty()) {
-                    throw new StuckDeferredAttrException(stuckVars);
+            
+            public Type doAttr(DeferredType<?> dt, Symbol msym, Resolve.MethodResolutionPhase phase, ResultInfo result) {
+                Type owntype = dt.getType(msym, phase);
+                if (owntype == null) {
+                    Assert.check(result.pt.tag != NONE);
+                    List<Type> stuckVars = stuckVars(dt, result);
+                    if (stuckVars.nonEmpty()) {
+                        throw new StuckDeferredAttrException(stuckVars);
+                    }                
+                    JCTree newTree = new TreeCopier<Object>(make).copy(dt.tree);
+                    Env<AttrContext> speculativeEnv = dt.env.dup(newTree, dt.env.info.dup(dt.env.info.scope.dupUnshared()));
+                    speculativeEnv.info.scope.owner = dt.env.info.scope.owner;
+                    Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
+                    Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;                
+                    final JavaFileObject currentSource = log.currentSourceFile();
+                    try {
+                        speculativeEnv.info.speculativeAttrRound = true;
+                        log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
+                        log.deferredDiagFilter = new Filter<JCDiagnostic>() {
+                            public boolean accepts(JCDiagnostic t) {
+                                return t.getDiagnosticSource().getFile().equals(currentSource);
+                            }
+                        };
+                        owntype = attr.attribTree(newTree, speculativeEnv, result);
+                        SpeculativeAttrContext speculativeContext = new SpeculativeAttrContext(newTree, phase, result);
+                        speculativeContext.undo();
+                        dt.addContext(msym, speculativeContext);
+                    } catch (Abort ex) {
+                        //if some very bad condition occurred during deferred attribution
+                        //we should dump all errors before killing javac
+                        log.reportDeferredDiagnostics();
+                        throw ex;
+                    } finally {
+                        unenterScanner.scan(newTree);
+                        log.deferredDiagFilter = prevDeferDiagsFilter;
+                        log.deferredDiagnostics = prevDeferredDiags;                    
+                    }
                 }
-                JCTree newTree = new TreeCopier<Object>(make).copy(dt.tree);
-                Env<AttrContext> speculativeEnv = dt.env.dup(newTree, dt.env.info.dup(dt.env.info.scope.dupUnshared()));
-                speculativeEnv.info.scope.owner = dt.env.info.scope.owner;
-                Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
-                Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;                
-                final JavaFileObject currentSource = log.currentSourceFile();
-                try {
-                    speculativeEnv.info.speculativeAttrRound = true;
-                    log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
-                    log.deferredDiagFilter = new Filter<JCDiagnostic>() {
-                        public boolean accepts(JCDiagnostic t) {
-                            return t.getDiagnosticSource().getFile().equals(currentSource);
-                        }
-                    };
-                    return attr.attribTree(newTree, speculativeEnv, result);
-                } catch (Abort ex) {
-                    //if some very bad condition occurred during deferred attribution
-                    //we should dump all errors before killing javac
-                    log.reportDeferredDiagnostics();
-                    throw ex;
-                } finally {
-                    unenterScanner.scan(newTree);
-                    log.deferredDiagFilter = prevDeferDiagsFilter;
-                    log.deferredDiagnostics = prevDeferredDiags;                    
-                }
+                return owntype;
             }
 
             TreeScanner unenterScanner = new TreeScanner() {
@@ -227,14 +293,22 @@
             };
         },
         new AttrRound(AttrMode.RECOVERY) {
-            public Type doAttr(DeferredType<?> dt, ResultInfo result) {
-                JCTree tree2 = TreeInfo.skipParens(dt.tree);
-                if (tree2.hasTag(LAMBDA) ||
-                        tree2.hasTag(REFERENCE) ||
-                        tree2.hasTag(CONDEXPR)) {
-                    return dt;
-                } else if (dt.qtype.tag == NONE) {
-                    Type owntype = attr.attribExpr(tree2, dt.env);
+            public Type doAttr(DeferredType<?> dt, Symbol msym, Resolve.MethodResolutionPhase phase, ResultInfo result) {                
+                if (dt.qtype.tag == NONE) {
+                    Type owntype = dt.getType(msym, phase);
+                    if (owntype == null) {
+                        JCTree tree2 = TreeInfo.skipParens(dt.tree);
+                        if (tree2.hasTag(LAMBDA) ||
+                                tree2.hasTag(REFERENCE) ||
+                                tree2.hasTag(CONDEXPR)) {
+                            //propagate those deferred types to the
+                            //diagnostic formatter
+                            return dt;
+                        } else if (dt.qtype.tag == NONE) {
+                            owntype = attr.attribExpr(tree2, dt.env);
+                            dt.qtype = owntype;
+                        }
+                    }
                     dt.qtype = owntype;
                 }
                 return dt.qtype;
@@ -242,31 +316,65 @@
         }
     };
     
+    
+    
     /**
-     * Type-check a deferred type using given deferred attribution mode using
-     * a default expected context (j.l.Object)
+     * Process a type - a deferred type is checked using given deferred attribution mode
+     * and a default expected context (j.l.Object) - this is used to retrieve a previously
+     * processed speculative deferred type, or to go through a recovery attribution step.
      */
-    Type attribDeferred(DeferredType<?> dt, AttrMode mode) {
-        return attribDeferred(dt, mode, attr.unknownExprInfo);
+    Type attribDeferred(Type t, AttrMode mode, Symbol msym, Resolve.MethodResolutionPhase phase) {
+        return attribDeferred(t, mode, msym, phase, attr.unknownExprInfo);
     }
 
     /**
-     * Type-check a deferred type using given deferred attribution mode using
-     * given expected context
+     * Process a type - a deferred type is checked using given deferred attribution mode
+     * and given expected context
      */
-    Type attribDeferred(DeferredType<?> dt, AttrMode mode, final ResultInfo result) {
-        if (dt.qtype.tag != NONE && !result.checkContext.inferenceContext().free(dt.qtype)) {
-            return result.check(dt.tree, dt.qtype);
+    Type attribDeferred(Type t, AttrMode mode, Symbol msym, Resolve.MethodResolutionPhase phase, final ResultInfo result) {
+        if (t.tag != DEFERRED) {
+            return t;
         } else {
-            for (AttrRound attrRound : attrRounds) {
-                if (attrRound.accept(mode)) {
-                    return attrRound.doAttr(dt, result);
+            DeferredType<?> dt = (DeferredType<?>)t;
+            if (dt.qtype.tag != NONE && !result.checkContext.inferenceContext().free(dt.qtype)) {
+                return result.check(dt.tree, dt.qtype);
+            } else {
+                for (AttrRound attrRound : attrRounds) {
+                    if (attrRound.accept(mode)) {
+                        return attrRound.doAttr(dt, msym, phase, result);
+                    }
                 }
+                Assert.error("No matching attribution round");
+                return null;
             }
-            Assert.error("No matching attribution round");
-            return null;
         }
     }
+    
+    /**
+     * Process a list of types where deferred types are checked using given
+     * deferred attribution mode and default expected context (j.l.Object) - 
+     * this is used to retrieve a previously processed speculative deferred type,
+     * or to go through a recovery attribution step.
+     */
+    List<Type> attribDeferred(List<Type> ts, AttrMode mode, Symbol msym, Resolve.MethodResolutionPhase phase) {
+        ListBuffer<Type> buf = ListBuffer.lb();
+        for (Type t : ts) {
+            buf.append(attribDeferred(t, mode, msym, phase));
+        }
+        return buf.toList();
+    }
+    
+    /**
+     * Process a list of types where deferred types are checked using given
+     * deferred attribution mode and given expected context
+     */
+    List<Type> attribDeferred(List<Type> ts, AttrMode mode, Symbol msym, Resolve.MethodResolutionPhase phase, ResultInfo resultInfo) {
+        ListBuffer<Type> buf = ListBuffer.lb();
+        for (Type t : ts) {
+            buf.append(attribDeferred(t, mode, msym, phase, resultInfo));
+        }
+        return buf.toList();
+    }
 
     /**
      * Check as to whether a given deferred type can be type-checked using
--- a/src/share/classes/com/sun/tools/javac/comp/GraphInfer.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/GraphInfer.java	Thu Aug 09 18:18:44 2012 +0100
@@ -87,42 +87,44 @@
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final GraphInferenceContext inferenceContext = new GraphInferenceContext(tvars);
-        
-        rs.checkRawArgumentsAcceptable(env, resolveContext.attrMode(), inferenceContext, argtypes, mt.getParameterTypes(),
-                allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
-        
-        if (resultInfo != null &&
-                !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
-            Type to = resultInfo.pt.tag == NONE ? mt.getReturnType() : resultInfo.pt;
-            Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
-            if (!types.isSubtypeNoCapture(qtype1,
-                    qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to) &&
-                    !types.isSubtypeNoCapture(mt.getReturnType(), resultInfo.checkContext.inferenceContext().asFree(to, types))) {                
-                throw inferenceException
-                        .setMessage("infer.no.conforming.instance.exists",
-                        inferenceContext.restvars(), mt.getReturnType(), to);
+        inferenceException.clear();
+        try {
+            rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext, argtypes, mt.getParameterTypes(),
+                    allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
+
+            if (resultInfo != null &&
+                    !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
+                Type to = resultInfo.pt.tag == NONE ? mt.getReturnType() : resultInfo.pt;
+                Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
+                if (!types.isSubtypeNoCapture(qtype1,
+                        qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to) &&
+                        !types.isSubtypeNoCapture(mt.getReturnType(), resultInfo.checkContext.inferenceContext().asFree(to, types))) {                
+                    throw inferenceException
+                            .setMessage("infer.no.conforming.instance.exists",
+                            inferenceContext.restvars(), mt.getReturnType(), to);
+                }
+
+                if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
+                    //propagate inference context outwards and exit
+                    inferenceContext.dupTo(resultInfo.checkContext.inferenceContext());
+                    return mt;
+                }
             }
 
-            if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
-                //propagate inference context outwards and exit
-                inferenceContext.dupTo(resultInfo.checkContext.inferenceContext());
-                return mt;
+            // minimize as yet undetermined type variables
+            inferenceContext.solve();
+
+            mt = (MethodType)inferenceContext.asInstType(mt, types);
+
+            if (resultInfo != null && rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
+                log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
             }
-        }
 
-        // minimize as yet undetermined type variables
-        inferenceContext.solve();
-
-        mt = (MethodType)inferenceContext.asInstType(mt, types);
-        
-        inferenceContext.finish();
-        
-        if (resultInfo != null && rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
-            log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
-        }
-        
-        // return instantiated version of method type
-        return mt;
+            // return instantiated version of method type
+            return mt;
+        } finally {
+            inferenceContext.notifyChange(types);
+        }    
     }
     
     private void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) {
@@ -466,12 +468,12 @@
          */
         void dupTo(InferenceContext that) {
             that.undetvars = that.undetvars.appendList(undetvars);
-            that.pendingChecks = that.pendingChecks.appendList(pendingChecks);
+            that.freeTypeListeners = that.freeTypeListeners.appendList(freeTypeListeners);
         }
         
         private void solve(SolverStrategy ss) {
             InferenceSolver s = new InferenceSolver(this);
-            s.solve(ss);
+            s.solve(ss);            
         }
         
         /**
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Aug 09 18:18:44 2012 +0100
@@ -63,12 +63,33 @@
         inferenceException = new InferenceException(diags);
     }
 
+    /**
+     * This exception class is design to store a list of diagnostics corresponding
+     * to inference errors that can arise during a method applicability check.
+     */
     public static class InferenceException extends InapplicableMethodException {
         private static final long serialVersionUID = 0;
+        
+        List<JCDiagnostic> messages = List.nil();
 
         InferenceException(JCDiagnostic.Factory diags) {
             super(diags);
         }
+
+        @Override
+        InapplicableMethodException setMessage(JCDiagnostic diag) {
+            messages = messages.append(diag);
+            return this;
+        }
+
+        @Override
+        public JCDiagnostic getDiagnostic() {
+            return messages.head;
+        }
+        
+        void clear() {
+            messages = List.nil();
+        }
     }
 
     protected final InferenceException inferenceException;
@@ -316,6 +337,7 @@
      */
     Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env,
                                             MethodSymbol spMethod,  // sig. poly. method or null if none
+                                            Resolve.MethodResolutionContext resolveContext,
                                             List<Type> argtypes) {
         final Type restype;
 
@@ -345,7 +367,7 @@
                 restype = syms.objectType;
         }
 
-        List<Type> paramtypes = Type.map(argtypes, implicitArgType);
+        List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext));
         List<Type> exType = spMethod != null ?
             spMethod.getThrownTypes() :
             List.of(syms.throwableType); // make it throw all exceptions
@@ -357,20 +379,31 @@
         return mtype;
     }
     //where
-        Mapping implicitArgType = new Mapping ("implicitArgType") {
-                public Type apply(Type t) {
-                    if (t.tag == DEFERRED) {
-                        DeferredAttr.DeferredType<?> dt = (DeferredAttr.DeferredType<?>)t;
-                        t = deferredAttr.attribDeferred(dt, DeferredAttr.AttrMode.SPECULATIVE);
-                    }
-                    t = types.erasure(t);
-                    if (t.tag == BOT)
-                        // nulls type as the marker type Null (which has no instances)
-                        // infer as java.lang.Void for now
-                        t = types.boxedClass(syms.voidType).type;
-                    return t;
+        class ImplicitArgType extends Mapping {
+            
+            Symbol msym;
+            Resolve.MethodResolutionContext resolveContext;
+
+            public ImplicitArgType(Symbol msym, Resolve.MethodResolutionContext resolveContext) {
+                super("implicitArgType");
+                this.msym = msym;
+                this.resolveContext = resolveContext;
+            }
+            
+            public Type apply(Type t) {
+                if (t.tag == DEFERRED) {
+                    //the deferred type has already been checked against the method at this point
+                    DeferredAttr.DeferredType<?> dt = (DeferredAttr.DeferredType<?>)t;
+                    t = dt.getType(msym, resolveContext.step);
                 }
-        };
+                t = types.erasure(t);
+                if (t.tag == BOT)
+                    // nulls type as the marker type Null (which has no instances)
+                    // infer as java.lang.Void for now
+                    t = types.boxedClass(syms.voidType).type;
+                return t;
+            }
+        }
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Inference context">
@@ -389,14 +422,21 @@
         * (i.e. subtyping checks) might need to be redone after all inference variables
         * have been fixed.
         */   
-        interface PendingCheck {
-            void eval();
+        static abstract class FreeTypeListener {
+            
+            Type freeType;
+
+            FreeTypeListener(Type freeType) {
+                this.freeType = freeType;
+            }
+            
+            abstract void typeInferred(Type inferredType);
         }
         
         /** list of inference vars as undet vars */
         List<Type> undetvars;
         
-        ListBuffer<PendingCheck> pendingChecks = ListBuffer.lb();
+        List<FreeTypeListener> freeTypeListeners = List.nil();
         
         public InferenceContext(List<Type> inferenceVars, final Types types) {
             this(inferenceVars, types, true);
@@ -531,19 +571,25 @@
         /**
          * Add custom hook for performing post-inference action
          */
-        void addPendingCheck(PendingCheck pc) {
-            pendingChecks.append(pc);
+        void addFreeTypeListener(FreeTypeListener ftl) {
+            freeTypeListeners = freeTypeListeners.prepend(ftl);
         }
 
         /**
          * Mark the inference context as complete and trigger evaluation
          * of all deferred checks.
          */
-        void finish() {
-            Assert.check(restvars().isEmpty());
-            for (PendingCheck pc : pendingChecks) {
-                pc.eval();
+        void notifyChange(Types types) {
+            List<FreeTypeListener> newFreeTypeListeners = List.nil();
+            for (FreeTypeListener ftl : freeTypeListeners) {                
+                Type instType = asInstType(ftl.freeType, types);
+                if (!free(instType)) {
+                    ftl.typeInferred(instType);
+                } else {
+                    newFreeTypeListeners = newFreeTypeListeners.prepend(ftl);
+                }
             }
+            freeTypeListeners = newFreeTypeListeners;
         }
         
         abstract void solveAny(List<Type> stuckvars);
--- a/src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/LegacyInfer.java	Thu Aug 09 18:18:44 2012 +0100
@@ -204,38 +204,39 @@
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final InferenceContext inferenceContext = new LegacyInferenceContext(tvars, true);
-        
-        rs.checkRawArgumentsAcceptable(env, resultInfo != null ? DeferredAttr.AttrMode.CHECK : DeferredAttr.AttrMode.SPECULATIVE, inferenceContext, argtypes, mt.getParameterTypes(),
-                allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
+        inferenceException.clear();
+        try {
+            rs.checkRawArgumentsAcceptable(env, msym, resultInfo != null ? DeferredAttr.AttrMode.CHECK : DeferredAttr.AttrMode.SPECULATIVE, inferenceContext, argtypes, mt.getParameterTypes(),
+                    allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext));
 
-        // minimize as yet undetermined type variables
-        for (Type t : inferenceContext.undetvars) {
-            minimizeInst((UndetVar)t, inferenceContext);
-        }
-        
-        checkWithinBounds(inferenceContext, warn);
+            // minimize as yet undetermined type variables
+            for (Type t : inferenceContext.undetvars) {
+                minimizeInst((UndetVar)t, inferenceContext);
+            }
 
-        mt = (MethodType)inferenceContext.asInstType(mt, types);
-        
-        List<Type> restvars = inferenceContext.restvars(); 
-        
-        if (!restvars.isEmpty() && resultInfo != null &&
-                !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
-            if (resultInfo != null) {
-                instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo);
-                checkWithinBounds(inferenceContext, warn);
-                mt = (MethodType)inferenceContext.asInstType(mt, types);
-                inferenceContext.finish();
-                if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
-                    log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
+            checkWithinBounds(inferenceContext, warn);
+
+            mt = (MethodType)inferenceContext.asInstType(mt, types);
+
+            List<Type> restvars = inferenceContext.restvars(); 
+
+            if (!restvars.isEmpty() && resultInfo != null &&
+                    !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
+                if (resultInfo != null) {
+                    instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo);
+                    checkWithinBounds(inferenceContext, warn);
+                    mt = (MethodType)inferenceContext.asInstType(mt, types);
+                    if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
+                        log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
+                    }
                 }
             }
-        } else if (restvars.isEmpty()) {
-            inferenceContext.finish();
+            inferenceContext.notifyChange(types);
+            // return instantiated version of method type
+            return mt;
+        } finally {
+            inferenceContext.notifyChange(types);
         }
-        
-        // return instantiated version of method type
-        return mt;
     }
     
     @Override
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Aug 07 19:01:55 2012 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Aug 09 18:18:44 2012 +0100
@@ -33,7 +33,7 @@
 import com.sun.tools.javac.comp.Check.CheckContext;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
 import com.sun.tools.javac.comp.Infer.InferenceContext;
-import com.sun.tools.javac.comp.Infer.InferenceContext.PendingCheck;
+import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
@@ -225,9 +225,12 @@
             }
         }
         String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
+        DeferredAttr.AttrMode attrMode = success ? DeferredAttr.AttrMode.SPECULATIVE :
+                DeferredAttr.AttrMode.RECOVERY;
         JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
                 site.tsym, mostSpecificPos, currentResolutionContext.step,
-                methodArguments(argtypes), methodArguments(typeargtypes));
+                methodArguments(deferredAttr.attribDeferred(argtypes, attrMode, bestSoFar, currentResolutionContext.step)),
+                methodArguments(typeargtypes));
         JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
         log.report(d);
     }
@@ -260,6 +263,17 @@
     static boolean isStatic(Env<AttrContext> env) {
         return env.info.staticLevel > env.outer.info.staticLevel;
     }
+    
+    /**
+     * A name designates an operator if it consists
+     * of a non-empty sequence of operator symbols +-~!/*%&|^<>=
+     */
+    boolean isOperator(Name name) {
+       int i = 0;
+       while (i < name.getByteLength() &&
+              "+-~!*/%&|^<>=".indexOf(name.getByteAt(i)) >= 0) i++;
+       return i > 0 && i == name.getByteLength();
+    }
 
     /** An environment is an "initializer" if it is a constructor or
      *  an instance initializer.
@@ -510,7 +524,7 @@
                                     currentResolutionContext,
                                     warn);
 
-        checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(),
+        checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(),
                                 allowBoxing, useVarargs, warn);
         return mt;
     }
@@ -557,13 +571,14 @@
     /** Check if a parameter list accepts a list of args.
      */
     boolean argumentsAcceptable(Env<AttrContext> env,
+                                Symbol msym,
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn) {
         try {
-            checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn);
+            checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn);
             return true;
         } catch (InapplicableMethodException ex) {
             return false;
@@ -610,12 +625,13 @@
     };
 
     void checkRawArgumentsAcceptable(Env<AttrContext> env,
+                                Symbol msym,
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 boolean allowBoxing,
                                 boolean useVarargs,
                                 Warner warn) {
-        checkRawArgumentsAcceptable(env, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
+        checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
                 allowBoxing, useVarargs, warn, resolveHandler);
     }
 
@@ -638,6 +654,7 @@
      * A method check handler (see above) is used in order to report errors.
      */
     void checkRawArgumentsAcceptable(final Env<AttrContext> env,
+                                Symbol msym,
                                 DeferredAttr.AttrMode mode,
                                 final Infer.InferenceContext inferenceContext,
                                 List<Type> argtypes,
@@ -697,7 +714,7 @@
                 ResultInfo mresult = e.getValue();
                 mresult = mresult.dup(inferenceContext.asInstType(mresult.pt, types));
                 try {
-                    deferredAttr.attribDeferred(ptype, mode, mresult);
+                    deferredAttr.attribDeferred(ptype, mode, msym, currentResolutionContext.step, mresult);
                 } catch (DeferredAttr.StuckDeferredAttrException ex) {
                     for (Type t : ex.tvars) {
                         if (!stuckVars.contains(t)) {
@@ -722,9 +739,10 @@
     
     void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
         if (inferenceContext.free(t)) {
-            inferenceContext.addPendingCheck(new PendingCheck() {
-                public void eval() {
-                    varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
+            inferenceContext.addFreeTypeListener(new FreeTypeListener(t) {
+                @Override
+                void typeInferred(Type inferredType) {
+                    varargsAccessible(env, inferredType, handler, inferenceContext);
                 }
             });
         } else {
@@ -843,16 +861,13 @@
             this.diags = diags;
         }
         InapplicableMethodException setMessage() {
-            this.diagnostic = null;
-            return this;
+            return setMessage((JCDiagnostic)null);
         }
         InapplicableMethodException setMessage(String key) {
-            this.diagnostic = key != null ? diags.fragment(key) : null;
-            return this;
+            return setMessage(this.diagnostic = key != null ? diags.fragment(key) : null);
         }
         InapplicableMethodException setMessage(String key, Object... args) {
-            this.diagnostic = key != null ? diags.fragment(key, args) : null;
-            return this;
+            return setMessage(key != null ? diags.fragment(key, args) : null);
         }
         InapplicableMethodException setMessage(JCDiagnostic diag) {
             this.diagnostic = diag;
@@ -1121,11 +1136,9 @@
         case MTH:
             if (m1 == m2) return m1;
             boolean m1SignatureMoreSpecific =
-                    signatureMoreSpecific(argtypes, env, site, adjustVarargs(m1, m2, useVarargs),
-                    adjustVarargs(m2, m1, useVarargs), allowBoxing, useVarargs);
+                    signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
             boolean m2SignatureMoreSpecific =
-                    signatureMoreSpecific(argtypes, env, site, adjustVarargs(m2, m1, useVarargs),
-                    adjustVarargs(m1, m2, useVarargs), allowBoxing, useVarargs);
+                    signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
             if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
                 Type mt1 = types.memberType(site, m1);
                 Type mt2 = types.memberType(site, m2);
@@ -1208,11 +1221,13 @@
     }
     //where
     private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
-        Type mtype1 = types.memberType(site, m1);
-        Type mtype2 = types.memberType(site, m2);
+        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, m2, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
+        if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
             return true;
         }
         
@@ -1243,7 +1258,10 @@
                 //for structural arguments only - check that corresponding formals
                 //are related - if so replace formal with <null>
                 hasStructuralPoly = true;
-                if (!isStructuralSubtype(f1, f2, (DeferredType<?>)actual)) {
+                DeferredType<?> dt = (DeferredType<?>)actual;
+                Type t1 = deferredAttr.attribDeferred(dt, DeferredAttr.AttrMode.SPECULATIVE, m1, currentResolutionContext.step);
+                Type t2 = deferredAttr.attribDeferred(dt, DeferredAttr.AttrMode.SPECULATIVE, m2, currentResolutionContext.step);
+                if (!isStructuralSubtype(t1, t2)) {
                     //not structural subtypes - simply fail
                     return false;
                 } else {
@@ -1254,7 +1272,7 @@
             newFormals.append(newFormal);
             if (newFormals.length() > mtype2.getParameterTypes().length()) {
                 //expand m2's type so as to fit the new formal arity (varargs)
-                m2.type = types.createMethodTypeWithParameters(m2.type, m2.type.getParameterTypes().append(f2));
+                m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
             }
 
             formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
@@ -1270,7 +1288,7 @@
             newFormals.append(t);
         }
         //check if invocation (with tweaked args) is more specific
-        return invocationMoreSpecific(env, site, m2, newFormals.toList(), allowBoxing, useVarargs);
+        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) {
@@ -1317,16 +1335,8 @@
         }
     }
     //where
-    boolean isStructuralSubtype(Type s, Type t, DeferredType<?> actual) {
-        try {
-            //should happen rarely - but we should optimize this up
-            s = deferredAttr.attribDeferred(actual, DeferredAttr.AttrMode.SPECULATIVE, attr.new ResultInfo(VAL, s));
-            t = deferredAttr.attribDeferred(actual, DeferredAttr.AttrMode.SPECULATIVE, attr.new ResultInfo(VAL, t));
-        } catch (Infer.InferenceException ex) {
-            //something went wrong during functional interface wildcard inference
-            //this is unexpectedas the method was deemed applicable
-            Assert.error();
-        }
+    boolean isStructuralSubtype(Type s, Type t) {
+
         Type ret_s = types.findDescriptorType(s).getReturnType();
         Type ret_t = types.findDescriptorType(t).getReturnType();
         
@@ -1816,7 +1826,7 @@
                   boolean qualified,
                   List<Type> argtypes,
                   List<Type> typeargtypes) {
-        argtypes = Type.map(argtypes, deferredCompleter);
+        argtypes = Type.map(argtypes, new ErroneousArgMapping(sym, name));
         if (sym.kind >= AMBIGUOUS) {
             ResolveError errSym = (ResolveError)sym;
             if (!site.isErroneous() &&
@@ -1828,17 +1838,27 @@
         return sym;
     }
     //where
-        Type.Mapping deferredCompleter = new Type.Mapping("forceCompleter") {
+        class ErroneousArgMapping extends Type.Mapping {
+            
+            Symbol msym;            
+
+            public ErroneousArgMapping(Symbol errSym, Name name) {
+                super("erroneousArgMapping");
+                this.msym = errSym.kind == WRONG_MTH && !isOperator(name) ?
+                        ((InapplicableSymbolError)errSym).errCandidate().sym :
+                        errSym;
+            }
+            
             @Override
             public Type apply(Type t) {
                 if (t.tag == DEFERRED) {
                     DeferredType<?> dt = (DeferredType<?>)t;
-                    return chk.checkNonVoid(dt.tree, deferredAttr.attribDeferred(dt, DeferredAttr.AttrMode.RECOVERY));
+                    return chk.checkNonVoid(dt.tree, deferredAttr.attribDeferred(dt, DeferredAttr.AttrMode.RECOVERY, msym, currentResolutionContext.firstErroneousResolutionPhase()));
                 } else {
                     return t;
                 }
             }
-        };
+        }
 
     /** Same as original access(), but without location.
      */
@@ -2050,7 +2070,7 @@
                                             Symbol spMethod,
                                             List<Type> argtypes) {
         Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
-                (MethodSymbol)spMethod, argtypes);
+                (MethodSymbol)spMethod, currentResolutionContext, argtypes);
         for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) {
             if (types.isSameType(mtype, sym.type)) {
                return sym;
@@ -2172,9 +2192,9 @@
                 Symbol errSym =
                         currentResolutionContext.resolutionCache.get(currentResolutionContext.firstErroneousResolutionPhase());
                 final JCDiagnostic details = errSym.kind == WRONG_MTH ?
-                                currentResolutionContext.candidates.head.details :
+                                ((InapplicableSymbolError)errSym).errCandidate().details :
                                 null;
-                errSym = new ResolveError(WRONG_MTH, "diamond error") {
+                errSym = new InapplicableSymbolError(errSym.kind, "diamondError") {
                     @Override
                     JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
                             Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
@@ -2785,17 +2805,6 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes);
-
-        /**
-         * A name designates an operator if it consists
-         * of a non-empty sequence of operator symbols +-~!/*%&|^<>=
-         */
-        boolean isOperator(Name name) {
-            int i = 0;
-            while (i < name.getByteLength() &&
-                   "+-~!*/%&|^<>=".indexOf(name.getByteAt(i)) >= 0) i++;
-            return i > 0 && i == name.getByteLength();
-        }
     }
 
     /**
@@ -3237,10 +3246,10 @@
         private Map<MethodResolutionPhase, Symbol> resolutionCache =
             new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class);
 
-        private MethodResolutionPhase step = null;
+        MethodResolutionPhase step = null;
 
-        private boolean internalResolution = false;
-        private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
+        boolean internalResolution = false;
+        DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
 
         private MethodResolutionPhase firstErroneousResolutionPhase() {
             MethodResolutionPhase bestSoFar = BASIC;
--- a/test/tools/javac/lambda/TargetType20.out	Tue Aug 07 19:01:55 2012 -0700
+++ b/test/tools/javac/lambda/TargetType20.out	Thu Aug 09 18:18:44 2012 +0100
@@ -1,2 +1,2 @@
-TargetType20.java:41:10: compiler.err.cant.apply.symbol.1: kindname.method, call, TargetType20.SAM2<Z>,TargetType20.SAM2<Z>, compiler.misc.type.lambda,compiler.misc.type.lambda, kindname.class, TargetType20.Test, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object)
+TargetType20.java:41:10: compiler.err.cant.apply.symbol.1: kindname.method, call, TargetType20.SAM2<Z>,TargetType20.SAM2<Z>, TargetType20.SAM2<java.lang.String>,TargetType20.SAM2<java.lang.String>, kindname.class, TargetType20.Test, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object)
 1 error