# HG changeset patch # User mcimadamore # Date 1360697109 0 # Node ID ab55670d2e6279cfe7407b4ca53791c4366497bb # Parent d1f59adb0d835f313cb1df299574d2fdfc4ee792 8007464: Add graph inference support Summary: Add support for more aggressive type-inference scheme Reviewed-by: jjg diff -r d1f59adb0d83 -r ab55670d2e62 langtools/src/share/classes/com/sun/tools/javac/code/Source.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Tue Feb 12 19:25:09 2013 +0000 @@ -221,7 +221,7 @@ public boolean allowIntersectionTypesInCast() { return compareTo(JDK1_8) >= 0; } - public boolean allowEarlyReturnConstraints() { + public boolean allowGraphInference() { return compareTo(JDK1_8) >= 0; } public boolean allowStructuralMostSpecific() { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Feb 12 19:25:09 2013 +0000 @@ -4152,7 +4152,9 @@ } private Type capture(Type type) { - return types.capture(type); + //do not capture free types + return resultInfo.checkContext.inferenceContext().free(type) ? + type : types.capture(type); } private void validateTypeAnnotations(JCTree tree) { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Tue Feb 12 19:25:09 2013 +0000 @@ -234,7 +234,7 @@ dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase); return speculativeTree.type; case CHECK: - Assert.check(dt.mode == AttrMode.SPECULATIVE); + Assert.check(dt.mode != null); return attr.attribTree(dt.tree, dt.env, resultInfo); } Assert.error(); @@ -242,6 +242,13 @@ } }; + DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() { + public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { + Assert.check(deferredAttrContext.mode == AttrMode.CHECK); + return dt.tree.type = Type.noType; + } + }; + /** * The 'mode' in which the deferred type is to be type-checked */ @@ -382,7 +389,7 @@ if (!progress) { //remove all variables that have already been instantiated //from the list of stuck variables - inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars))); + inferenceContext.solveAny(List.from(stuckVars), warn); inferenceContext.notifyChange(); } } @@ -431,7 +438,15 @@ return true; case CHECK: if (stuckVars.nonEmpty()) { - return false; + //stuck expression - see if we can propagate + if (deferredAttrContext.parent != emptyDeferredAttrContext && + Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) { + deferredAttrContext.parent.deferredAttrNodes.add(this); + dt.check(resultInfo, List.nil(), dummyCompleter); + return true; + } else { + return false; + } } else { dt.check(resultInfo, stuckVars, basicCompleter); return true; diff -r d1f59adb0d83 -r ab55670d2e62 langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,22 +25,30 @@ package com.sun.tools.javac.comp; -import com.sun.tools.javac.code.*; -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.code.Type.*; -import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; -import com.sun.tools.javac.comp.DeferredAttr.AttrMode; -import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; -import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; +import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph; +import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node; +import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; +import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; import java.util.HashMap; import java.util.Map; +import java.util.Set; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; import static com.sun.tools.javac.code.TypeTag.*; @@ -55,19 +63,15 @@ protected static final Context.Key inferKey = new Context.Key(); - /** A value for prototypes that admit any type, including polymorphic ones. */ - public static final Type anyPoly = new Type(NONE, null); - + Resolve rs; + Check chk; Symtab syms; Types types; - Check chk; - Resolve rs; - DeferredAttr deferredAttr; + JCDiagnostic.Factory diags; Log log; - JCDiagnostic.Factory diags; - /** Should we inject return-type constraints earlier? */ - boolean allowEarlyReturnConstraints; + /** should the graph solver be used? */ + boolean allowGraphInference; public static Infer instance(Context context) { Infer instance = context.get(inferKey); @@ -78,17 +82,22 @@ protected Infer(Context context) { context.put(inferKey, this); + + rs = Resolve.instance(context); + chk = Check.instance(context); syms = Symtab.instance(context); types = Types.instance(context); - rs = Resolve.instance(context); - deferredAttr = DeferredAttr.instance(context); + diags = JCDiagnostic.Factory.instance(context); log = Log.instance(context); - chk = Check.instance(context); - diags = JCDiagnostic.Factory.instance(context); inferenceException = new InferenceException(diags); - allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints(); + Options options = Options.instance(context); + allowGraphInference = Source.instance(context).allowGraphInference() + && options.isUnset("useLegacyInference"); } + /** A value for prototypes that admit any type, including polymorphic ones. */ + public static final Type anyPoly = new Type(NONE, null); + /** * This exception class is design to store a list of diagnostics corresponding * to inference errors that can arise during a method applicability check. @@ -118,140 +127,12 @@ } } - final InferenceException inferenceException; - -/*************************************************************************** - * Mini/Maximization of UndetVars - ***************************************************************************/ - - /** Instantiate undetermined type variable to its minimal upper bound. - * Throw a NoInstanceException if this not possible. - */ - void maximizeInst(UndetVar that, Warner warn) throws InferenceException { - List hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter); - if (that.getBounds(InferenceBound.EQ).isEmpty()) { - if (hibounds.isEmpty()) - that.inst = syms.objectType; - else if (hibounds.tail.isEmpty()) - that.inst = hibounds.head; - else - that.inst = types.glb(hibounds); - } else { - that.inst = that.getBounds(InferenceBound.EQ).head; - } - if (that.inst == null || - that.inst.isErroneous()) - throw inferenceException - .setMessage("no.unique.maximal.instance.exists", - that.qtype, hibounds); - } + protected final InferenceException inferenceException; - private Filter boundFilter = new Filter() { - @Override - public boolean accepts(Type t) { - return !t.isErroneous() && !t.hasTag(BOT); - } - }; - - /** Instantiate undetermined type variable to the lub of all its lower bounds. - * Throw a NoInstanceException if this not possible. - */ - void minimizeInst(UndetVar that, Warner warn) throws InferenceException { - List lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter); - if (that.getBounds(InferenceBound.EQ).isEmpty()) { - if (lobounds.isEmpty()) { - //do nothing - the inference variable is under-constrained - return; - } else if (lobounds.tail.isEmpty()) - that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head; - else { - that.inst = types.lub(lobounds); - } - if (that.inst == null || that.inst.hasTag(ERROR)) - throw inferenceException - .setMessage("no.unique.minimal.instance.exists", - that.qtype, lobounds); - } else { - that.inst = that.getBounds(InferenceBound.EQ).head; - } - } - -/*************************************************************************** - * Exported Methods - ***************************************************************************/ - + // /** - * Instantiate uninferred inference variables (JLS 15.12.2.8). First - * if the method return type is non-void, we derive constraints from the - * expected type - then we use declared bound well-formedness to derive additional - * constraints. If no instantiation exists, or if several incomparable - * best instantiations exist throw a NoInstanceException. - */ - public void instantiateUninferred(DiagnosticPosition pos, - InferenceContext inferenceContext, - MethodType mtype, - Attr.ResultInfo resultInfo, - Warner warn) throws InferenceException { - while (true) { - boolean stuck = true; - for (Type t : inferenceContext.undetvars) { - UndetVar uv = (UndetVar)t; - if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() || - !inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) { - maximizeInst((UndetVar)t, warn); - stuck = false; - } - } - if (inferenceContext.restvars().isEmpty()) { - //all variables have been instantiated - exit - break; - } else if (stuck) { - //some variables could not be instantiated because of cycles in - //upper bounds - provide a (possibly recursive) default instantiation - instantiateAsUninferredVars(inferenceContext); - break; - } else { - //some variables have been instantiated - replace newly instantiated - //variables in remaining upper bounds and continue - for (Type t : inferenceContext.undetvars) { - UndetVar uv = (UndetVar)t; - uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types); - } - } - } - } - - /** - * Infer cyclic inference variables as described in 15.12.2.8. - */ - private void instantiateAsUninferredVars(InferenceContext inferenceContext) { - ListBuffer todo = ListBuffer.lb(); - //step 1 - create fresh tvars - for (Type t : inferenceContext.undetvars) { - UndetVar uv = (UndetVar)t; - if (uv.inst == null) { - TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner); - fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null); - todo.append(uv); - uv.inst = fresh_tvar.type; - } - } - //step 2 - replace fresh tvars in their bounds - List formals = inferenceContext.inferenceVars(); - for (Type t : todo) { - UndetVar uv = (UndetVar)t; - TypeVar ct = (TypeVar)uv.inst; - ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct))); - if (ct.bound.isErroneous()) { - //report inference error if glb fails - reportBoundError(uv, BoundErrorKind.BAD_UPPER); - } - formals = formals.tail; - } - } - - /** Instantiate a generic method type by finding instantiations for all its - * inference variables so that it can be applied to a given argument type list. + * Main inference entry point - instantiate a generic method type + * using given argument types and (possibly) an expected target-type. */ public Type instantiateMethod(Env env, List tvars, @@ -267,259 +148,144 @@ //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG final InferenceContext inferenceContext = new InferenceContext(tvars); inferenceException.clear(); + try { + DeferredAttr.DeferredAttrContext deferredAttrContext = + resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); - DeferredAttr.DeferredAttrContext deferredAttrContext = - resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); + methodCheck.argumentsAcceptable(env, deferredAttrContext, + argtypes, mt.getParameterTypes(), warn); - try { - methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn); - - if (resultInfo != null && allowEarlyReturnConstraints && + if (allowGraphInference && + resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { - generateReturnConstraints(mt, inferenceContext, resultInfo); + //inject return constraints earlier + checkWithinBounds(inferenceContext, warn); //propagation + generateReturnConstraints(resultInfo, mt, inferenceContext); + //propagate outwards if needed + if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { + //propagate inference context outwards and exit + inferenceContext.dupTo(resultInfo.checkContext.inferenceContext()); + deferredAttrContext.complete(); + return mt; + } } deferredAttrContext.complete(); // minimize as yet undetermined type variables - for (Type t : inferenceContext.undetvars) { - minimizeInst((UndetVar)t, warn); + if (allowGraphInference) { + inferenceContext.solve(warn); + } else { + inferenceContext.solveLegacy(true, warn, LegacyInferenceSteps.EQ_LOWER.steps); //minimizeInst } - checkWithinBounds(inferenceContext, warn); - mt = (MethodType)inferenceContext.asInstType(mt); - List restvars = inferenceContext.restvars(); + if (!allowGraphInference && + inferenceContext.restvars().nonEmpty() && + resultInfo != null && + !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { + generateReturnConstraints(resultInfo, mt, inferenceContext); + inferenceContext.solveLegacy(false, warn, LegacyInferenceSteps.EQ_UPPER.steps); //maximizeInst + mt = (MethodType)inferenceContext.asInstType(mt); + } - if (!restvars.isEmpty()) { - if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { - if (!allowEarlyReturnConstraints) { - generateReturnConstraints(mt, inferenceContext, resultInfo); - } - instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn); - checkWithinBounds(inferenceContext, warn); - mt = (MethodType)inferenceContext.asInstType(mt); - if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) { - log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt); - } - } + 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; } finally { - inferenceContext.notifyChange(); - } - } - //where - void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) { - if (resultInfo != null) { - Type to = resultInfo.pt; - if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { - to = mt.getReturnType().isPrimitiveOrVoid() ? - mt.getReturnType() : syms.objectType; - } - Type qtype1 = inferenceContext.asFree(mt.getReturnType()); - Warner retWarn = new Warner(); - if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) || - //unchecked conversion is not allowed - retWarn.hasLint(Lint.LintCategory.UNCHECKED)) { - throw inferenceException - .setMessage("infer.no.conforming.instance.exists", - inferenceContext.restvars(), mt.getReturnType(), to); - } - } - } - - /** check that type parameters are within their bounds. - */ - void checkWithinBounds(InferenceContext inferenceContext, - Warner warn) throws InferenceException { - //step 1 - check compatibility of instantiated type w.r.t. initial bounds - for (Type t : inferenceContext.undetvars) { - UndetVar uv = (UndetVar)t; - uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types); - checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars()); - if (!inferenceContext.restvars().contains(uv.qtype)) { - Type inst = inferenceContext.asInstType(t); - for (Type u : uv.getBounds(InferenceBound.UPPER)) { - if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u), warn)) { - reportBoundError(uv, BoundErrorKind.UPPER); - } - } - for (Type l : uv.getBounds(InferenceBound.LOWER)) { - Assert.check(!inferenceContext.free(l)); - if (!types.isSubtypeUnchecked(l, inst, warn)) { - reportBoundError(uv, BoundErrorKind.LOWER); - } - } - for (Type e : uv.getBounds(InferenceBound.EQ)) { - Assert.check(!inferenceContext.free(e)); - if (!types.isSameType(inst, e)) { - reportBoundError(uv, BoundErrorKind.EQ); - } - } - } - } - - //step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds - for (Type t : inferenceContext.undetvars) { - UndetVar uv = (UndetVar)t; - //check eq bounds consistency - Type eq = null; - for (Type e : uv.getBounds(InferenceBound.EQ)) { - Assert.check(!inferenceContext.free(e)); - if (eq != null && !types.isSameType(e, eq)) { - reportBoundError(uv, BoundErrorKind.EQ); - } - eq = e; - for (Type l : uv.getBounds(InferenceBound.LOWER)) { - Assert.check(!inferenceContext.free(l)); - if (!types.isSubtypeUnchecked(l, e, warn)) { - reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER); - } - } - for (Type u : uv.getBounds(InferenceBound.UPPER)) { - if (inferenceContext.free(u)) continue; - if (!types.isSubtypeUnchecked(e, u, warn)) { - reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); - } - } + if (resultInfo != null || !allowGraphInference) { + inferenceContext.notifyChange(); + } else { + inferenceContext.notifyChange(inferenceContext.boundedVars()); } } } - void checkCompatibleUpperBounds(UndetVar uv, List tvars) { - // VGJ: sort of inlined maximizeInst() below. Adding - // bounds can cause lobounds that are above hibounds. - ListBuffer hiboundsNoVars = ListBuffer.lb(); - for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) { - if (!t.containsAny(tvars)) { - hiboundsNoVars.append(t); + /** + * Generate constraints from the generic method's return type. If the method + * call occurs in a context where a type T is expected, use the expected + * type to derive more constraints on the generic method inference variables. + */ + void generateReturnConstraints(Attr.ResultInfo resultInfo, + MethodType mt, InferenceContext inferenceContext) { + Type qtype1 = inferenceContext.asFree(mt.getReturnType()); + Type to = returnConstraintTarget(qtype1, resultInfo.pt); + Assert.check(allowGraphInference || !resultInfo.checkContext.inferenceContext().free(to), + "legacy inference engine cannot handle constraints on both sides of a subtyping assertion"); + //we need to skip capture? + Warner retWarn = new Warner(); + if (!resultInfo.checkContext.compatible(qtype1, resultInfo.checkContext.inferenceContext().asFree(to), retWarn) || + //unchecked conversion is not allowed + retWarn.hasLint(Lint.LintCategory.UNCHECKED)) { + throw inferenceException + .setMessage("infer.no.conforming.instance.exists", + inferenceContext.restvars(), mt.getReturnType(), to); + } + } + //where + private Type returnConstraintTarget(Type from, Type to) { + if (from.hasTag(VOID)) { + return syms.voidType; + } else if (to.hasTag(NONE)) { + return from.isPrimitive() ? from : syms.objectType; + } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) { + if (!allowGraphInference) { + //if legacy, just return boxed type + return types.boxedClass(to).type; + } + //if graph inference we need to skip conflicting boxed bounds... + UndetVar uv = (UndetVar)from; + for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { + Type boundAsPrimitive = types.unboxedType(t); + if (boundAsPrimitive == null) continue; + if (types.isConvertible(boundAsPrimitive, to)) { + //effectively skip return-type constraint generation (compatibility) + return syms.objectType; + } + } + return types.boxedClass(to).type; + } else { + return to; } } - List hibounds = hiboundsNoVars.toList(); - Type hb = null; - if (hibounds.isEmpty()) - hb = syms.objectType; - else if (hibounds.tail.isEmpty()) - hb = hibounds.head; - else - hb = types.glb(hibounds); - if (hb == null || hb.isErroneous()) - reportBoundError(uv, BoundErrorKind.BAD_UPPER); - } - enum BoundErrorKind { - BAD_UPPER() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("incompatible.upper.bounds", uv.qtype, - uv.getBounds(InferenceBound.UPPER)); - } - }, - BAD_EQ_UPPER() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype, - uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER)); - } - }, - BAD_EQ_LOWER() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype, - uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER)); - } - }, - UPPER() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, - uv.getBounds(InferenceBound.UPPER)); - } - }, - LOWER() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, - uv.getBounds(InferenceBound.LOWER)); - } - }, - EQ() { - @Override - InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { - return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, - uv.getBounds(InferenceBound.EQ)); + /** + * Infer cyclic inference variables as described in 15.12.2.8. + */ + private void instantiateAsUninferredVars(List vars, InferenceContext inferenceContext) { + ListBuffer todo = ListBuffer.lb(); + //step 1 - create fresh tvars + for (Type t : vars) { + UndetVar uv = (UndetVar)inferenceContext.asFree(t); + List upperBounds = uv.getBounds(InferenceBound.UPPER); + if (Type.containsAny(upperBounds, vars)) { + TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner); + fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null); + todo.append(uv); + uv.inst = fresh_tvar.type; + } else if (upperBounds.nonEmpty()) { + uv.inst = types.glb(upperBounds); + } else { + uv.inst = syms.objectType; } - }; - - abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv); - } - //where - void reportBoundError(UndetVar uv, BoundErrorKind bk) { - throw bk.setMessage(inferenceException, uv); - } - - // - /** - * 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 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()); - Assert.check(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 descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes(); - if (descParameterTypes.size() != paramTypes.size()) { - checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda")); - return types.createErrorType(funcInterface); + } + //step 2 - replace fresh tvars in their bounds + List formals = vars; + for (Type t : todo) { + UndetVar uv = (UndetVar)t; + TypeVar ct = (TypeVar)uv.inst; + ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct))); + if (ct.bound.isErroneous()) { + //report inference error if glb fails + reportBoundError(uv, BoundErrorKind.BAD_UPPER); } - for (Type p : descParameterTypes) { - if (!types.isSameType(funcInterfaceContext.asFree(p), paramTypes.head)) { - checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); - return types.createErrorType(funcInterface); - } - paramTypes = paramTypes.tail; - } - List actualTypeargs = funcInterface.getTypeArguments(); - for (Type t : funcInterfaceContext.undetvars) { - UndetVar uv = (UndetVar)t; - if (funcInterfaceContext.boundedVars().contains(uv.qtype)) { - minimizeInst(uv, types.noWarnings); - if (uv.inst == null && - Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) { - maximizeInst(uv, types.noWarnings); - } - } else { - uv.inst = actualTypeargs.head; - } - Assert.check(uv.inst != null); - actualTypeargs = actualTypeargs.tail; - } - Type owntype = funcInterfaceContext.asInstType(formalInterface); - 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 owntype; + formals = formals.tail; } } - // /** * Compute a synthetic method type corresponding to the requested polymorphic @@ -573,7 +339,7 @@ class ImplicitArgType extends DeferredAttr.DeferredTypeMap { public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) { - deferredAttr.super(AttrMode.SPECULATIVE, msym, phase); + rs.deferredAttr.super(AttrMode.SPECULATIVE, msym, phase); } public Type apply(Type t) { @@ -587,6 +353,920 @@ } /** + * This method is used to infer a suitable target SAM in case the original + * SAM type contains one or more wildcards. An inference process is applied + * so that wildcard bounds, as well as explicit lambda/method ref parameters + * (where applicable) are used to constraint the solution. + */ + public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface, + List 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()); + + Assert.check(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 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), paramTypes.head)) { + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); + return types.createErrorType(funcInterface); + } + paramTypes = paramTypes.tail; + } + + try { + funcInterfaceContext.solve(funcInterfaceContext.boundedVars(), types.noWarnings); + } catch (InferenceException ex) { + checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); + } + + List actualTypeargs = funcInterface.getTypeArguments(); + for (Type t : funcInterfaceContext.undetvars) { + UndetVar uv = (UndetVar)t; + if (uv.inst == null) { + uv.inst = actualTypeargs.head; + } + actualTypeargs = actualTypeargs.tail; + } + + Type owntype = funcInterfaceContext.asInstType(formalInterface); + 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 owntype; + } + } + // + + // + /** + * Check bounds and perform incorporation + */ + void checkWithinBounds(InferenceContext inferenceContext, + Warner warn) throws InferenceException { + MultiUndetVarListener mlistener = new MultiUndetVarListener(inferenceContext.undetvars); + try { + while (true) { + mlistener.reset(); + if (!allowGraphInference) { + //in legacy mode we lack of transitivity, so bound check + //cannot be run in parallel with other incoprporation rounds + for (Type t : inferenceContext.undetvars) { + UndetVar uv = (UndetVar)t; + IncorporationStep.CHECK_BOUNDS.apply(uv, inferenceContext, warn); + } + } + for (Type t : inferenceContext.undetvars) { + UndetVar uv = (UndetVar)t; + //bound incorporation + EnumSet incorporationSteps = allowGraphInference ? + incorporationStepsGraph : incorporationStepsLegacy; + for (IncorporationStep is : incorporationSteps) { + is.apply(uv, inferenceContext, warn); + } + } + if (!mlistener.changed || !allowGraphInference) break; + } + } + finally { + mlistener.detach(); + } + } + //where + /** + * This listener keeps track of changes on a group of inference variable + * bounds. Note: the listener must be detached (calling corresponding + * method) to make sure that the underlying inference variable is + * left in a clean state. + */ + class MultiUndetVarListener implements UndetVar.UndetVarListener { + + int rounds; + boolean changed; + List undetvars; + + public MultiUndetVarListener(List undetvars) { + this.undetvars = undetvars; + for (Type t : undetvars) { + UndetVar uv = (UndetVar)t; + uv.listener = this; + } + } + + public void varChanged(UndetVar uv, Set ibs) { + //avoid non-termination + if (rounds < MAX_INCORPORATION_STEPS) { + changed = true; + } + } + + void reset() { + rounds++; + changed = false; + } + + void detach() { + for (Type t : undetvars) { + UndetVar uv = (UndetVar)t; + uv.listener = null; + } + } + }; + + /** max number of incorporation rounds */ + static final int MAX_INCORPORATION_STEPS = 100; + + /** + * This enumeration defines an entry point for doing inference variable + * bound incorporation - it can be used to inject custom incorporation + * logic into the basic bound checking routine + */ + enum IncorporationStep { + /** + * Performs basic bound checking - i.e. is the instantiated type for a given + * inference variable compatible with its bounds? + */ + CHECK_BOUNDS() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), infer.types); + infer.checkCompatibleUpperBounds(uv, inferenceContext); + if (uv.inst != null) { + Type inst = uv.inst; + for (Type u : uv.getBounds(InferenceBound.UPPER)) { + if (!infer.types.isSubtypeUnchecked(inst, inferenceContext.asFree(u), warn)) { + infer.reportBoundError(uv, BoundErrorKind.UPPER); + } + } + for (Type l : uv.getBounds(InferenceBound.LOWER)) { + if (!infer.types.isSubtypeUnchecked(inferenceContext.asFree(l), inst, warn)) { + infer.reportBoundError(uv, BoundErrorKind.LOWER); + } + } + for (Type e : uv.getBounds(InferenceBound.EQ)) { + if (!infer.types.isSameType(inst, inferenceContext.asFree(e))) { + infer.reportBoundError(uv, BoundErrorKind.EQ); + } + } + } + } + }, + /** + * Check consistency of equality constraints. This is a slightly more aggressive + * inference routine that is designed as to maximize compatibility with JDK 7. + * Note: this is not used in graph mode. + */ + EQ_CHECK_LEGACY() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + Type eq = null; + for (Type e : uv.getBounds(InferenceBound.EQ)) { + Assert.check(!inferenceContext.free(e)); + if (eq != null && !infer.types.isSameType(e, eq)) { + infer.reportBoundError(uv, BoundErrorKind.EQ); + } + eq = e; + for (Type l : uv.getBounds(InferenceBound.LOWER)) { + Assert.check(!inferenceContext.free(l)); + if (!infer.types.isSubtypeUnchecked(l, e, warn)) { + infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER); + } + } + for (Type u : uv.getBounds(InferenceBound.UPPER)) { + if (inferenceContext.free(u)) continue; + if (!infer.types.isSubtypeUnchecked(e, u, warn)) { + infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); + } + } + } + } + }, + /** + * Check consistency of equality constraints. + */ + EQ_CHECK() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type e : uv.getBounds(InferenceBound.EQ)) { + if (e.containsAny(inferenceContext.inferenceVars())) continue; + for (Type u : uv.getBounds(InferenceBound.UPPER)) { + if (!infer.types.isSubtypeUnchecked(e, inferenceContext.asFree(u), warn)) { + infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER); + } + } + for (Type l : uv.getBounds(InferenceBound.LOWER)) { + if (!infer.types.isSubtypeUnchecked(inferenceContext.asFree(l), e, warn)) { + infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha <: T} and {@code alpha :> S} + * perform {@code S <: T} (which could lead to new bounds). + */ + CROSS_UPPER_LOWER() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { + for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { + if (!inferenceContext.inferenceVars().contains(b1) && + !inferenceContext.inferenceVars().contains(b2) && + infer.types.asSuper(b2, b1.tsym) != null) { + infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1)); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha <: T} and {@code alpha == S} + * perform {@code S <: T} (which could lead to new bounds). + */ + CROSS_UPPER_EQ() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b1 : uv.getBounds(InferenceBound.UPPER)) { + for (Type b2 : uv.getBounds(InferenceBound.EQ)) { + if (!inferenceContext.inferenceVars().contains(b1) && + !inferenceContext.inferenceVars().contains(b2) && + infer.types.asSuper(b2, b1.tsym) != null) { + infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1)); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha :> S} and {@code alpha == T} + * perform {@code S <: T} (which could lead to new bounds). + */ + CROSS_EQ_LOWER() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b1 : uv.getBounds(InferenceBound.EQ)) { + for (Type b2 : uv.getBounds(InferenceBound.LOWER)) { + if (!inferenceContext.inferenceVars().contains(b1) && + !inferenceContext.inferenceVars().contains(b2) && + infer.types.asSuper(b2, b1.tsym) != null) { + infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1)); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha <: beta} propagate lower bounds + * from alpha to beta; also propagate upper bounds from beta to alpha. + */ + PROP_UPPER() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b : uv.getBounds(InferenceBound.UPPER)) { + if (inferenceContext.inferenceVars().contains(b)) { + UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + //alpha <: beta + //1. copy alpha's lower to beta's + for (Type l : uv.getBounds(InferenceBound.LOWER)) { + uv2.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types); + } + //2. copy beta's upper to alpha's + for (Type u : uv2.getBounds(InferenceBound.UPPER)) { + uv.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha :> beta} propagate lower bounds + * from beta to alpha; also propagate upper bounds from alpha to beta. + */ + PROP_LOWER() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b : uv.getBounds(InferenceBound.LOWER)) { + if (inferenceContext.inferenceVars().contains(b)) { + UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + //alpha :> beta + //1. copy alpha's upper to beta's + for (Type u : uv.getBounds(InferenceBound.UPPER)) { + uv2.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types); + } + //2. copy beta's lower to alpha's + for (Type l : uv2.getBounds(InferenceBound.LOWER)) { + uv.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types); + } + } + } + } + }, + /** + * Given a bound set containing {@code alpha == beta} propagate lower/upper + * bounds from alpha to beta and back. + */ + PROP_EQ() { + public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) { + Infer infer = inferenceContext.infer(); + for (Type b : uv.getBounds(InferenceBound.EQ)) { + if (inferenceContext.inferenceVars().contains(b)) { + UndetVar uv2 = (UndetVar)inferenceContext.asFree(b); + //alpha == beta + //1. copy all alpha's bounds to beta's + for (InferenceBound ib : InferenceBound.values()) { + for (Type b2 : uv.getBounds(ib)) { + if (b2 != uv2) { + uv2.addBound(ib, inferenceContext.asInstType(b2), infer.types); + } + } + } + //2. copy all beta's bounds to alpha's + for (InferenceBound ib : InferenceBound.values()) { + for (Type b2 : uv2.getBounds(ib)) { + if (b2 != uv) { + uv.addBound(ib, inferenceContext.asInstType(b2), infer.types); + } + } + } + } + } + } + }; + + abstract void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn); + } + + /** incorporation steps to be executed when running in legacy mode */ + EnumSet incorporationStepsLegacy = EnumSet.of(IncorporationStep.EQ_CHECK_LEGACY); + + /** incorporation steps to be executed when running in graph mode */ + EnumSet incorporationStepsGraph = + EnumSet.complementOf(EnumSet.of(IncorporationStep.EQ_CHECK_LEGACY)); + + /** + * Make sure that the upper bounds we got so far lead to a solvable inference + * variable by making sure that a glb exists. + */ + void checkCompatibleUpperBounds(UndetVar uv, InferenceContext inferenceContext) { + List hibounds = + Type.filter(uv.getBounds(InferenceBound.UPPER), new BoundFilter(inferenceContext)); + Type hb = null; + if (hibounds.isEmpty()) + hb = syms.objectType; + else if (hibounds.tail.isEmpty()) + hb = hibounds.head; + else + hb = types.glb(hibounds); + if (hb == null || hb.isErroneous()) + reportBoundError(uv, BoundErrorKind.BAD_UPPER); + } + //where + protected static class BoundFilter implements Filter { + + InferenceContext inferenceContext; + + public BoundFilter(InferenceContext inferenceContext) { + this.inferenceContext = inferenceContext; + } + + @Override + public boolean accepts(Type t) { + return !t.isErroneous() && !inferenceContext.free(t) && + !t.hasTag(BOT); + } + }; + + /** + * This enumeration defines all possible bound-checking related errors. + */ + enum BoundErrorKind { + /** + * The (uninstantiated) inference variable has incompatible upper bounds. + */ + BAD_UPPER() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("incompatible.upper.bounds", uv.qtype, + uv.getBounds(InferenceBound.UPPER)); + } + }, + /** + * An equality constraint is not compatible with an upper bound. + */ + BAD_EQ_UPPER() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype, + uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER)); + } + }, + /** + * An equality constraint is not compatible with a lower bound. + */ + BAD_EQ_LOWER() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype, + uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER)); + } + }, + /** + * Instantiated inference variable is not compatible with an upper bound. + */ + UPPER() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, + uv.getBounds(InferenceBound.UPPER)); + } + }, + /** + * Instantiated inference variable is not compatible with a lower bound. + */ + LOWER() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, + uv.getBounds(InferenceBound.LOWER)); + } + }, + /** + * Instantiated inference variable is not compatible with an equality constraint. + */ + EQ() { + @Override + InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) { + return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, + uv.getBounds(InferenceBound.EQ)); + } + }; + + abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv); + } + + /** + * Report a bound-checking error of given kind + */ + void reportBoundError(UndetVar uv, BoundErrorKind bk) { + throw bk.setMessage(inferenceException, uv); + } + // + + // + /** + * Graph inference strategy - act as an input to the inference solver; a strategy is + * composed of two ingredients: (i) find a node to solve in the inference graph, + * and (ii) tell th engine when we are done fixing inference variables + */ + interface GraphStrategy { + /** + * Pick the next node (leaf) to solve in the graph + */ + Node pickNode(InferenceGraph g); + /** + * Is this the last step? + */ + boolean done(); + } + + /** + * Simple solver strategy class that locates all leaves inside a graph + * and picks the first leaf as the next node to solve + */ + abstract class LeafSolver implements GraphStrategy { + public Node pickNode(InferenceGraph g) { + Assert.check(!g.nodes.isEmpty(), "No nodes to solve!"); + return g.nodes.get(0); + } + } + + /** + * This solver uses an heuristic to pick the best leaf - the heuristic + * tries to select the node that has maximal probability to contain one + * or more inference variables in a given list + */ + abstract class BestLeafSolver extends LeafSolver { + + List varsToSolve; + + BestLeafSolver(List varsToSolve) { + this.varsToSolve = varsToSolve; + } + + /** + * Computes the cost associated with a given node; the cost is computed + * as the total number of type-variables that should be eagerly instantiated + * in order to get to some of the variables in {@code varsToSolve} from + * a given node + */ + void computeCostIfNeeded(Node n, Map costMap) { + if (costMap.containsKey(n)) { + return; + } else if (!Collections.disjoint(n.data, varsToSolve)) { + costMap.put(n, n.data.size()); + } else { + int subcost = Integer.MAX_VALUE; + costMap.put(n, subcost); //avoid loops + for (Node n2 : n.getDependencies()) { + computeCostIfNeeded(n2, costMap); + subcost = Math.min(costMap.get(n2), subcost); + } + //update cost map to reflect real cost + costMap.put(n, subcost == Integer.MAX_VALUE ? + Integer.MAX_VALUE : + n.data.size() + subcost); + } + } + + /** + * Pick the leaf that minimize cost + */ + @Override + public Node pickNode(final InferenceGraph g) { + final Map costMap = new HashMap(); + ArrayList leaves = new ArrayList(); + for (Node n : g.nodes) { + computeCostIfNeeded(n, costMap); + if (n.isLeaf(n)) { + leaves.add(n); + } + } + Assert.check(!leaves.isEmpty(), "No nodes to solve!"); + Collections.sort(leaves, new java.util.Comparator() { + public int compare(Node n1, Node n2) { + return costMap.get(n1) - costMap.get(n2); + } + }); + return leaves.get(0); + } + } + + /** + * The inference process can be thought of as a sequence of steps. Each step + * instantiates an inference variable using a subset of the inference variable + * bounds, if certain condition are met. Decisions such as the sequence in which + * steps are applied, or which steps are to be applied are left to the inference engine. + */ + enum InferenceStep { + + /** + * Instantiate an inference variables using one of its (ground) equality + * constraints + */ + EQ(InferenceBound.EQ) { + @Override + Type solve(UndetVar uv, InferenceContext inferenceContext) { + return filterBounds(uv, inferenceContext).head; + } + }, + /** + * Instantiate an inference variables using its (ground) lower bounds. Such + * bounds are merged together using lub(). + */ + LOWER(InferenceBound.LOWER) { + @Override + Type solve(UndetVar uv, InferenceContext inferenceContext) { + Infer infer = inferenceContext.infer(); + List lobounds = filterBounds(uv, inferenceContext); + Type owntype = infer.types.lub(lobounds); + if (owntype.hasTag(ERROR)) { + throw infer.inferenceException + .setMessage("no.unique.minimal.instance.exists", + uv.qtype, lobounds); + } else { + return owntype; + } + } + }, + /** + * Instantiate an inference variables using its (ground) upper bounds. Such + * bounds are merged together using glb(). + */ + UPPER(InferenceBound.UPPER) { + @Override + Type solve(UndetVar uv, InferenceContext inferenceContext) { + Infer infer = inferenceContext.infer(); + List hibounds = filterBounds(uv, inferenceContext); + Type owntype = infer.types.glb(hibounds); + if (owntype.isErroneous()) { + throw infer.inferenceException + .setMessage("no.unique.maximal.instance.exists", + uv.qtype, hibounds); + } else { + return owntype; + } + } + }, + /** + * Like the former; the only difference is that this step can only be applied + * if all upper bounds are ground. + */ + UPPER_LEGACY(InferenceBound.UPPER) { + @Override + public boolean accepts(UndetVar t, InferenceContext inferenceContext) { + return !inferenceContext.free(t.getBounds(ib)); + } + + @Override + Type solve(UndetVar uv, InferenceContext inferenceContext) { + return UPPER.solve(uv, inferenceContext); + } + }; + + final InferenceBound ib; + + InferenceStep(InferenceBound ib) { + this.ib = ib; + } + + /** + * Find an instantiated type for a given inference variable within + * a given inference context + */ + abstract Type solve(UndetVar uv, InferenceContext inferenceContext); + + /** + * Can the inference variable be instantiated using this step? + */ + public boolean accepts(UndetVar t, InferenceContext inferenceContext) { + return filterBounds(t, inferenceContext).nonEmpty(); + } + + /** + * Return the subset of ground bounds in a given bound set (i.e. eq/lower/upper) + */ + List filterBounds(UndetVar uv, InferenceContext inferenceContext) { + return Type.filter(uv.getBounds(ib), new BoundFilter(inferenceContext)); + } + } + + /** + * This enumeration defines the sequence of steps to be applied when the + * solver works in legacy mode. The steps in this enumeration reflect + * the behavior of old inference routine (see JLS SE 7 15.12.2.7/15.12.2.8). + */ + enum LegacyInferenceSteps { + + EQ_LOWER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER)), + EQ_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.UPPER_LEGACY)); + + final EnumSet steps; + + LegacyInferenceSteps(EnumSet steps) { + this.steps = steps; + } + } + + /** + * This enumeration defines the sequence of steps to be applied when the + * graph solver is used. This order is defined so as to maximize compatibility + * w.r.t. old inference routine (see JLS SE 7 15.12.2.7/15.12.2.8). + */ + enum GraphInferenceSteps { + + EQ(EnumSet.of(InferenceStep.EQ)), + EQ_LOWER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER)), + EQ_LOWER_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER, InferenceStep.UPPER)); + + final EnumSet steps; + + GraphInferenceSteps(EnumSet steps) { + this.steps = steps; + } + } + + /** + * This is the graph inference solver - the solver organizes all inference variables in + * a given inference context by bound dependencies - in the general case, such dependencies + * would lead to a cyclic directed graph (hence the name); the dependency info is used to build + * an acyclic graph, where all cyclic variables are bundled together. An inference + * step corresponds to solving a node in the acyclic graph - this is done by + * relying on a given strategy (see GraphStrategy). + */ + class GraphSolver { + + InferenceContext inferenceContext; + Warner warn; + + GraphSolver(InferenceContext inferenceContext, Warner warn) { + this.inferenceContext = inferenceContext; + this.warn = warn; + } + + /** + * Solve variables in a given inference context. The amount of variables + * to be solved, and the way in which the underlying acyclic graph is explored + * depends on the selected solver strategy. + */ + void solve(GraphStrategy sstrategy) { + checkWithinBounds(inferenceContext, warn); //initial propagation of bounds + InferenceGraph inferenceGraph = new InferenceGraph(); + while (!sstrategy.done()) { + InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); + List varsToSolve = List.from(nodeToSolve.data); + inferenceContext.save(); + try { + //repeat until all variables are solved + outer: while (Type.containsAny(inferenceContext.restvars(), varsToSolve)) { + //for each inference phase + for (GraphInferenceSteps step : GraphInferenceSteps.values()) { + if (inferenceContext.solveBasic(varsToSolve, step.steps)) { + checkWithinBounds(inferenceContext, warn); + continue outer; + } + } + //no progress + throw inferenceException; + } + } + catch (InferenceException ex) { + inferenceContext.rollback(); + instantiateAsUninferredVars(varsToSolve, inferenceContext); + checkWithinBounds(inferenceContext, warn); + } + inferenceGraph.deleteNode(nodeToSolve); + } + } + + /** + * The dependencies between the inference variables that need to be solved + * form a (possibly cyclic) graph. This class reduces the original dependency graph + * to an acyclic version, where cyclic nodes are folded into a single 'super node'. + */ + class InferenceGraph { + + /** + * This class represents a node in the graph. Each node corresponds + * to an inference variable and has edges (dependencies) on other + * nodes. The node defines an entry point that can be used to receive + * updates on the structure of the graph this node belongs to (used to + * keep dependencies in sync). + */ + class Node extends GraphUtils.TarjanNode> { + + Set deps; + + Node(Type ivar) { + super(ListBuffer.of(ivar)); + this.deps = new HashSet(); + } + + @Override + public Iterable getDependencies() { + return deps; + } + + @Override + public String printDependency(GraphUtils.Node> to) { + StringBuilder buf = new StringBuilder(); + String sep = ""; + for (Type from : data) { + UndetVar uv = (UndetVar)inferenceContext.asFree(from); + for (Type bound : uv.getBounds(InferenceBound.values())) { + if (bound.containsAny(List.from(to.data))) { + buf.append(sep); + buf.append(bound); + sep = ","; + } + } + } + return buf.toString(); + } + + boolean isLeaf(Node n) { + //no deps, or only one self dep + return (n.deps.isEmpty() || + n.deps.size() == 1 && n.deps.contains(n)); + } + + void mergeWith(List nodes) { + for (Node n : nodes) { + Assert.check(n.data.length() == 1, "Attempt to merge a compound node!"); + data.appendList(n.data); + deps.addAll(n.deps); + } + //update deps + Set deps2 = new HashSet(); + for (Node d : deps) { + if (data.contains(d.data.first())) { + deps2.add(this); + } else { + deps2.add(d); + } + } + deps = deps2; + } + + void graphChanged(Node from, Node to) { + if (deps.contains(from)) { + deps.remove(from); + if (to != null) { + deps.add(to); + } + } + } + } + + /** the nodes in the inference graph */ + ArrayList nodes; + + InferenceGraph() { + initNodes(); + } + + /** + * Delete a node from the graph. This update the underlying structure + * of the graph (including dependencies) via listeners updates. + */ + public void deleteNode(Node n) { + Assert.check(nodes.contains(n)); + nodes.remove(n); + notifyUpdate(n, null); + } + + /** + * Notify all nodes of a change in the graph. If the target node is + * {@code null} the source node is assumed to be removed. + */ + void notifyUpdate(Node from, Node to) { + for (Node n : nodes) { + n.graphChanged(from, to); + } + } + + /** + * Create the graph nodes. First a simple node is created for every inference + * variables to be solved. Then Tarjan is used to found all connected components + * in the graph. For each component containing more than one node, a super node is + * created, effectively replacing the original cyclic nodes. + */ + void initNodes() { + ArrayList nodes = new ArrayList(); + for (Type t : inferenceContext.restvars()) { + nodes.add(new Node(t)); + } + for (Node n_i : nodes) { + Type i = n_i.data.first(); + for (Node n_j : nodes) { + Type j = n_j.data.first(); + UndetVar uv_i = (UndetVar)inferenceContext.asFree(i); + if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) { + //update i's deps + n_i.deps.add(n_j); + //update j's deps - only if i's bounds contain _exactly_ j + if (uv_i.getBounds(InferenceBound.values()).contains(j)) { + n_j.deps.add(n_i); + } + } + } + } + this.nodes = new ArrayList(); + for (List conSubGraph : GraphUtils.tarjan(nodes)) { + if (conSubGraph.length() > 1) { + Node root = conSubGraph.head; + root.mergeWith(conSubGraph.tail); + for (Node n : conSubGraph) { + notifyUpdate(n, root); + } + } + this.nodes.add(conSubGraph.head); + } + } + + /** + * Debugging: dot representation of this graph + */ + String toDot() { + StringBuilder buf = new StringBuilder(); + for (Type t : inferenceContext.undetvars) { + UndetVar uv = (UndetVar)t; + buf.append(String.format("var %s - upper bounds = %s, lower bounds = %s, eq bounds = %s\\n", + uv.qtype, uv.getBounds(InferenceBound.UPPER), uv.getBounds(InferenceBound.LOWER), + uv.getBounds(InferenceBound.EQ))); + } + return GraphUtils.toDot(nodes, "inferenceGraph" + hashCode(), buf.toString()); + } + } + } + // + + // + /** * Functional interface for defining inference callbacks. Certain actions * (i.e. subtyping checks) might need to be redone after all inference variables * have been fixed. @@ -603,7 +1283,7 @@ * it can be used as an entry point for performing upper/lower bound inference * (see InferenceKind). */ - class InferenceContext { + class InferenceContext { /** list of inference vars as undet vars */ List undetvars; @@ -611,6 +1291,9 @@ /** list of inference vars in this context */ List inferencevars; + /** backed up inference variables */ + List saved_undet; + java.util.Map> freeTypeListeners = new java.util.HashMap>(); @@ -782,10 +1465,14 @@ * of all deferred checks. */ void notifyChange() { + notifyChange(inferencevars.diff(restvars())); + } + + void notifyChange(List inferredVars) { InferenceException thrownEx = null; for (Map.Entry> entry : new HashMap>(freeTypeListeners).entrySet()) { - if (!Type.containsAny(entry.getValue(), restvars())) { + if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) { try { entry.getKey().typesInferred(this); freeTypeListeners.remove(entry.getKey()); @@ -803,20 +1490,153 @@ } } - void solveAny(List varsToSolve) { - boolean progress = false; - for (Type t : varsToSolve) { + /** + * Save the state of this inference context + */ + void save() { + ListBuffer buf = ListBuffer.lb(); + for (Type t : undetvars) { + UndetVar uv = (UndetVar)t; + UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types); + for (InferenceBound ib : InferenceBound.values()) { + for (Type b : uv.getBounds(ib)) { + uv2.addBound(ib, b, types); + } + } + uv2.inst = uv.inst; + buf.add(uv2); + } + saved_undet = buf.toList(); + } + + /** + * Restore the state of this inference context to the previous known checkpoint + */ + void rollback() { + Assert.check(saved_undet != null && saved_undet.length() == undetvars.length()); + undetvars = saved_undet; + saved_undet = null; + } + + /** + * Copy variable in this inference context to the given context + */ + void dupTo(final InferenceContext that) { + that.inferencevars = that.inferencevars.appendList(inferencevars); + that.undetvars = that.undetvars.appendList(undetvars); + //set up listeners to notify original inference contexts as + //propagated vars are inferred in new context + for (Type t : inferencevars) { + that.freeTypeListeners.put(new FreeTypeListener() { + public void typesInferred(InferenceContext inferenceContext) { + InferenceContext.this.notifyChange(); + } + }, List.of(t)); + } + } + + /** + * Solve with given graph strategy. + */ + private void solve(GraphStrategy ss, Warner warn) { + GraphSolver s = new GraphSolver(this, warn); + s.solve(ss); + } + + /** + * Solve all variables in this context. + */ + public void solve(Warner warn) { + solve(new LeafSolver() { + public boolean done() { + return restvars().isEmpty(); + } + }, warn); + } + + /** + * Solve all variables in the given list. + */ + public void solve(final List vars, Warner warn) { + solve(new BestLeafSolver(vars) { + public boolean done() { + return !free(asInstTypes(vars)); + } + }, warn); + } + + /** + * Solve at least one variable in given list. + */ + public void solveAny(List varsToSolve, Warner warn) { + checkWithinBounds(this, warn); //propagate bounds + List boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve); + if (boundedVars.isEmpty()) { + throw inferenceException.setMessage("cyclic.inference", + freeVarsIn(varsToSolve)); + } + solve(new BestLeafSolver(boundedVars) { + public boolean done() { + return instvars().intersect(varsToSolve).nonEmpty(); + } + }, warn); + } + + /** + * Apply a set of inference steps + */ + private boolean solveBasic(EnumSet steps) { + return solveBasic(inferencevars, steps); + } + + private boolean solveBasic(List varsToSolve, EnumSet steps) { + boolean changed = false; + for (Type t : varsToSolve.intersect(restvars())) { UndetVar uv = (UndetVar)asFree(t); - if (uv.inst == null) { - minimizeInst(uv, types.noWarnings); - if (uv.inst != null) { - progress = true; + for (InferenceStep step : steps) { + if (step.accepts(uv, this)) { + uv.inst = step.solve(uv, this); + changed = true; + break; } } } - if (!progress) { - throw inferenceException.setMessage("cyclic.inference", varsToSolve); + return changed; + } + + /** + * Instantiate inference variables in legacy mode (JLS 15.12.2.7, 15.12.2.8). + * During overload resolution, instantiation is done by doing a partial + * inference process using eq/lower bound instantiation. During check, + * we also instantiate any remaining vars by repeatedly using eq/upper + * instantiation, until all variables are solved. + */ + public void solveLegacy(boolean partial, Warner warn, EnumSet steps) { + while (true) { + boolean stuck = !solveBasic(steps); + if (restvars().isEmpty() || partial) { + //all variables have been instantiated - exit + break; + } else if (stuck) { + //some variables could not be instantiated because of cycles in + //upper bounds - provide a (possibly recursive) default instantiation + instantiateAsUninferredVars(restvars(), this); + break; + } else { + //some variables have been instantiated - replace newly instantiated + //variables in remaining upper bounds and continue + for (Type t : undetvars) { + UndetVar uv = (UndetVar)t; + uv.substBounds(inferenceVars(), instTypes(), types); + } + } } + checkWithinBounds(this, warn); + } + + private Infer infer() { + //back-door to infer + return Infer.this; } } diff -r d1f59adb0d83 -r ab55670d2e62 langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.util; + +/**

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class GraphUtils { + + /** + * This class is a basic abstract class for representing a node. + * A node is associated with a given data. + */ + public static abstract class Node { + public final D data; + + public Node(D data) { + this.data = data; + } + + public abstract Iterable> getDependencies(); + + public abstract String printDependency(Node to); + + @Override + public String toString() { + return data.toString(); + } + } + + /** + * This class specialized Node, by adding elements that are required in order + * to perform Tarjan computation of strongly connected components. + */ + public static abstract class TarjanNode extends Node implements Comparable> { + int index = -1; + int lowlink; + boolean active; + + public TarjanNode(D data) { + super(data); + } + + public abstract Iterable> getDependencies(); + + public int compareTo(TarjanNode o) { + return (index < o.index) ? -1 : (index == o.index) ? 0 : 1; + } + } + + /** + * Tarjan's algorithm to determine strongly connected components of a + * directed graph in linear time. Works on TarjanNode. + */ + public static > List> tarjan(Iterable nodes) { + ListBuffer> cycles = ListBuffer.lb(); + ListBuffer stack = ListBuffer.lb(); + int index = 0; + for (N node: nodes) { + if (node.index == -1) { + index += tarjan(node, index, stack, cycles); + } + } + return cycles.toList(); + } + + private static > int tarjan(N v, int index, ListBuffer stack, ListBuffer> cycles) { + v.index = index; + v.lowlink = index; + index++; + stack.prepend(v); + v.active = true; + for (TarjanNode nd: v.getDependencies()) { + @SuppressWarnings("unchecked") + N n = (N)nd; + if (n.index == -1) { + tarjan(n, index, stack, cycles); + v.lowlink = Math.min(v.lowlink, n.lowlink); + } else if (stack.contains(n)) { + v.lowlink = Math.min(v.lowlink, n.index); + } + } + if (v.lowlink == v.index) { + N n; + ListBuffer cycle = ListBuffer.lb(); + do { + n = stack.remove(); + n.active = false; + cycle.add(n); + } while (n != v); + cycles.add(cycle.toList()); + } + return index; + } + + /** + * Debugging: dot representation of a set of connected nodes. The resulting + * dot representation will use {@code Node.toString} to display node labels + * and {@code Node.printDependency} to display edge labels. The resulting + * representation is also customizable with a graph name and a header. + */ + public static String toDot(Iterable> nodes, String name, String header) { + StringBuilder buf = new StringBuilder(); + buf.append(String.format("digraph %s {\n", name)); + buf.append(String.format("label = \"%s\";\n", header)); + //dump nodes + for (TarjanNode n : nodes) { + buf.append(String.format("%s [label = \"%s\"];\n", n.hashCode(), n.toString())); + } + //dump arcs + for (TarjanNode from : nodes) { + for (TarjanNode to : from.getDependencies()) { + buf.append(String.format("%s -> %s [label = \" %s \"];\n", + from.hashCode(), to.hashCode(), from.printDependency(to))); + } + } + buf.append("}\n"); + return buf.toString(); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/6758789/T6758789b.out --- a/langtools/test/tools/javac/6758789/T6758789b.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/6758789/T6758789b.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,4 +1,4 @@ -T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo +T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo, T6758789a.Foo, kindname.class, T6758789a - compiler.err.warnings.and.werror 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/Diagnostics/6799605/T6799605.out --- a/langtools/test/tools/javac/Diagnostics/6799605/T6799605.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/Diagnostics/6799605/T6799605.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,4 +1,4 @@ -T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605,{(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605), (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.type.captureof: 1, ?, T6799605)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T))} +T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605,{(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605), (compiler.misc.incompatible.eq.upper.bounds: T, compiler.misc.type.captureof: 1, ?, T6799605)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T))} T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605,T6799605,{(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ?, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T))} T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605,T6799605,T6799605,{(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, m(T6799605,T6799605,T6799605), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 3, ?, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?))} 3 errors diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/diags/examples/CantApplyDiamond1.java --- a/langtools/test/tools/javac/diags/examples/CantApplyDiamond1.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/diags/examples/CantApplyDiamond1.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ // key: compiler.err.prob.found.req // key: compiler.misc.cant.apply.diamond.1 -// key: compiler.misc.inferred.do.not.conform.to.upper.bounds +// key: compiler.misc.incompatible.eq.upper.bounds // key: compiler.misc.diamond class CantApplyDiamond1 { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/diags/examples/InferredDoNotConformToEq.java --- a/langtools/test/tools/javac/diags/examples/InferredDoNotConformToEq.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/diags/examples/InferredDoNotConformToEq.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.inferred.do.not.conform.to.eq.bounds +// options: -source 7 -Xlint:-options import java.util.*; diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/diags/examples/InferredDoNotConformToUpper.java --- a/langtools/test/tools/javac/diags/examples/InferredDoNotConformToUpper.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/diags/examples/InferredDoNotConformToUpper.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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,7 @@ // key: compiler.err.cant.apply.symbol // key: compiler.misc.inferred.do.not.conform.to.upper.bounds +// options: -source 7 -Xlint:-options import java.util.*; diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/diags/examples/WhereFreshTvar.java --- a/langtools/test/tools/javac/diags/examples/WhereFreshTvar.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/diags/examples/WhereFreshTvar.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,7 +24,7 @@ // key: compiler.misc.where.fresh.typevar // key: compiler.misc.where.description.typevar // key: compiler.err.prob.found.req -// key: compiler.misc.inferred.do.not.conform.to.upper.bounds +// key: compiler.misc.inconvertible.types // options: -XDdiags=where,simpleNames // run: simple @@ -33,5 +33,5 @@ class WhereFreshTvar { > T m() {} - { List ls = m(); } + { Object o = (List)m(); } } diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/7015430/T7015430.out --- a/langtools/test/tools/javac/generics/7015430/T7015430.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/7015430/T7015430.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,14 +1,14 @@ -T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable +T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 -T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable +T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, , java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, , java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, , java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 -T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable +T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, , java.lang.Iterable, java.lang.Iterable, kindname.class, T7015430 T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/7151802/T7151802.out --- a/langtools/test/tools/javac/generics/7151802/T7151802.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/7151802/T7151802.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ T7151802.java:14:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get1, Z, T7151802.Foo, kindname.class, T7151802 -T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo +T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo, T7151802.Foo, kindname.class, T7151802 T7151802.java:30:36: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get5, compiler.misc.no.args, compiler.misc.no.args, kindname.class, T7151802 T7151802.java:38:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/diamond/neg/Neg06.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg06.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg06.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -Neg06.java:16:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number)) +Neg06.java:16:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/6278587/T6278587Neg.java --- a/langtools/test/tools/javac/generics/inference/6278587/T6278587Neg.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/6278587/T6278587Neg.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, 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,10 +23,11 @@ /* * @test - * @bug 6278587 + * @bug 6278587 8007464 * @summary Inference broken for subtypes of subtypes of F-bounded types * @author Peter von der Ah\u00e9 - * @compile/fail T6278587Neg.java + * @compile/fail -source 7 T6278587Neg.java + * @compile T6278587Neg.java */ public abstract class T6278587Neg { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/6638712/T6638712d.out --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712d.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712d.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List>, int,java.util.List>, kindname.class, T6638712d, (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.String, java.lang.Integer) +T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List>, int,java.util.List>, kindname.class, T6638712d, (compiler.misc.incompatible.eq.lower.bounds: U, java.lang.String, java.lang.Integer) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/6638712/T6638712e.out --- a/langtools/test/tools/javac/generics/inference/6638712/T6638712e.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/6638712/T6638712e.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Boolean,java.lang.Object) +T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Boolean,java.lang.Object) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/7154127/T7154127.java --- a/langtools/test/tools/javac/generics/inference/7154127/T7154127.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/7154127/T7154127.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,8 +1,9 @@ /** * @test /nodynamiccopyright/ - * @bug 7154127 + * @bug 7154127 8007464 * @summary Inference cleanup: remove bound check analysis from visitors in Types.java - * @compile/fail/ref=T7154127.out -XDrawDiagnostics T7154127.java + * @compile/fail/ref=T7154127.out -Xlint:-options -source 7 -XDrawDiagnostics T7154127.java + * @compile T7154127.java */ class T7154127 { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/7154127/T7154127.out --- a/langtools/test/tools/javac/generics/inference/7154127/T7154127.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/7154127/T7154127.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -T7154127.java:19:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B,T7154127.D) +T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B,T7154127.D) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/7177306/T7177306a.out --- a/langtools/test/tools/javac/generics/inference/7177306/T7177306a.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/7177306/T7177306a.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,4 +1,4 @@ -T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List +T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List T7177306a.java:13:33: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, java.util.List, java.util.List, kindname.class, T7177306a T7177306a.java:13:33: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7177306a, T7177306a - compiler.err.warnings.and.werror diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/7177306/T7177306e.java --- a/langtools/test/tools/javac/generics/inference/7177306/T7177306e.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/7177306/T7177306e.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,8 +1,9 @@ /** * @test /nodynamiccopyright/ - * @bug 7177306 + * @bug 7177306 8007464 * @summary Regression: unchecked method call does not erase return type - * @compile/fail/ref=T7177306e.out -XDrawDiagnostics T7177306e.java + * @compile/fail/ref=T7177306e.out -source 7 -Xlint:-options -XDrawDiagnostics T7177306e.java + * @compile/fail T7177306e.java */ import java.util.List; diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/inference/7177306/T7177306e.out --- a/langtools/test/tools/javac/generics/inference/7177306/T7177306e.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/inference/7177306/T7177306e.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -T7177306e.java:15:9: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List, java.util.List) +T7177306e.java:16:9: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List, java.util.List) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/generics/odersky/BadTest4.java --- a/langtools/test/tools/javac/generics/odersky/BadTest4.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/generics/odersky/BadTest4.java Tue Feb 12 19:25:09 2013 +0000 @@ -23,11 +23,12 @@ /* * @test - * @ bug + * @bug 8007464 * @summary Negative regression test from odersky * @author odersky * - * @compile/fail BadTest4.java + * @compile/fail -source 7 BadTest4.java + * @compile BadTest4.java */ class BadTest4 { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType14.out --- a/langtools/test/tools/javac/lambda/TargetType14.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType14.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String) +TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.lower.bounds: X, java.lang.Integer, java.lang.String) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType20.java --- a/langtools/test/tools/javac/lambda/TargetType20.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType20.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,10 +1,33 @@ /* - * @test /nodynamiccopyright/ + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test * @bug 8003280 * @summary Add lambda tests * complex case of lambda return type that depends on generic method * inference variable - * @compile/fail/ref=TargetType20.out -XDrawDiagnostics TargetType20.java + * @compile -XDrawDiagnostics TargetType20.java */ import java.util.*; diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType20.out --- a/langtools/test/tools/javac/lambda/TargetType20.out Tue Feb 12 13:36:56 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -TargetType20.java:19:10: compiler.err.cant.apply.symbol: kindname.method, call, TargetType20.SAM2,TargetType20.SAM2, @428,@459, kindname.class, TargetType20.Test, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object) -1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType28.out --- a/langtools/test/tools/javac/lambda/TargetType28.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType28.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,3 +1,2 @@ -TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.String) -TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.Integer) -2 errors +TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String,X, java.lang.Object,java.lang.Number) +1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType50.java --- a/langtools/test/tools/javac/lambda/TargetType50.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType50.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,9 +1,32 @@ /* - * @test /nodynamiccopyright/ + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test * @bug 8003280 * @summary Add lambda tests * bad stuck check for method reference leads to javac crash - * @compile/fail/ref=TargetType50.out -XDrawDiagnostics TargetType50.java + * @compile TargetType50.java */ import java.util.*; @@ -17,7 +40,7 @@ static Sink make() { return null; } } - > List m(Factory factory) { } + > List m(Factory factory) { return null; } void test() { List l1 = m(Sink::new); diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType50.out --- a/langtools/test/tools/javac/lambda/TargetType50.out Tue Feb 12 13:36:56 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink, TargetType50.Sink) -TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink, TargetType50.Sink) -2 errors diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType51.java --- a/langtools/test/tools/javac/lambda/TargetType51.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType51.java Tue Feb 12 19:25:09 2013 +0000 @@ -23,7 +23,9 @@ /* * @test - * @summary smoke test for combinator-like stuck analysis + * @bug 8005244 + * @summary Implement overload resolution as per latest spec EDR + * smoke test for combinator-like stuck analysis * @author Maurizio Cimadamore * @compile TargetType51.java */ diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType52.java --- a/langtools/test/tools/javac/lambda/TargetType52.java Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType52.java Tue Feb 12 19:25:09 2013 +0000 @@ -1,6 +1,8 @@ /* * @test /nodynamiccopyright/ - * @summary uncatched sam conversion failure exception lead to javac crash + * @bug 8005244 + * @summary Implement overload resolution as per latest spec EDR + * uncatched sam conversion failure exception lead to javac crash * @compile/fail/ref=TargetType52.out -XDrawDiagnostics TargetType52.java */ class TargetType52 { diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType52.out --- a/langtools/test/tools/javac/lambda/TargetType52.out Tue Feb 12 13:36:56 2013 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType52.out Tue Feb 12 19:25:09 2013 +0000 @@ -1,2 +1,2 @@ -TargetType52.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType52.FI>, @444, kindname.class, TargetType52, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: TargetType52.FI>)) +TargetType52.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType52.FI>, @525, kindname.class, TargetType52, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: TargetType52.FI>)) 1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType53.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType53.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * smoke test for graph inference + * @ignore awaits stream API: 800NNNN + * @compile TargetType53.java + */ +import java.util.*; +import java.util.stream.*; +import java.util.function.*; + +class TargetType53 { + +

List> perm(List

l) { return null; } + + void g(List>> l) { } + + void test() { + List>> l = + perm(Arrays.asList(s -> s.sorted())); + g(perm(Arrays.asList(s -> s.sorted()))); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType54.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType54.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * smoke test for graph inference + * @ignore awaits stream API: 800NNNN + * @compile TargetType54.java + */ +import java.util.stream.*; +import java.util.*; +import static java.util.stream.Collectors.*; + +class TargetType54 { + void test(Stream si) { + List l1 = si.collect(toList()); + List l2 = si.collect(toCollection(ArrayList::new)); + m(si.collect(toList())); + m(si.collect(toCollection(ArrayList::new))); + } + + void m(List l) { } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType55.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType55.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference + * support smoke test for graph inference + * @compile TargetType55.java + */ +import java.util.function.*; + +class TargetType55 { + + void m(Function collector) { } + + Function g(D d, BinaryOperator reducer) { return null; } + + public void test() { + m(g((Integer)null, (x,y)->1)); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType56.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType56.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * smoke test for graph inference + * @compile TargetType56.java + */ +class TargetType56 { + Z m(Z z) { return null; } + + void test() { + double d1 = m(1); + double d2 = m((Integer)null); + double d3 = m(m(1)); + double d4 = m(m((Integer)null)); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType57.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType57.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8007464 + * @summary Add graph inference support + * more smoke tests for graph inference + * @compile/fail/ref=TargetType57.out -XDrawDiagnostics TargetType57.java + */ +import java.util.*; +import java.util.function.*; + +class TargetType57 { + + void test(List list) { + m(list, s -> s.intValue(), s -> s.nonExistentMethod()); + } + + R m(List list, + Function f1, + Function f2) { return null; } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType57.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType57.out Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,2 @@ +TargetType57.java:14:42: compiler.err.cant.resolve.location.args: kindname.method, nonExistentMethod, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer) +1 error diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType58.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType58.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * more smoke tests for graph inference + * @ignore awaits stream API: 800NNNN + * @compile TargetType58.java + */ +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +class TargetType58 { + + void test(List li) { + g(li, s -> s.substream(200), Collections.emptyList()); + } + + , + I extends Iterable> Collection g(Collection coll, Function, S_OUT> f, I i) { + return null; + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType59.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType59.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * more smoke tests for graph inference + * @ignore awaits stream API: 800NNNN + * @compile TargetType59.java + */ +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +class TargetType59 { + + Collector m(Supplier supplier, BiConsumer accumulator) { + return null; + } + + > Collector test1(Supplier collectionFactory) { + return m(collectionFactory, Collection::add); + } + + Collector test2(Supplier sb) { + return m(sb, StringBuilder::append); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType61.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType61.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * check that new wildcards inference strategy doesn't run into 7190296 + * @compile TargetType61.java + */ +class TargetType61 { + + interface Stream { + void forEach(Sink sink); + } + + interface Sink { + void put(T t); + } + + public boolean add(CharSequence s) { return false; } + + public void addAll(Stream stream) { + stream.forEach(this::add); + stream.forEach(e -> { add(e); }); + } +} diff -r d1f59adb0d83 -r ab55670d2e62 langtools/test/tools/javac/lambda/TargetType62.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/lambda/TargetType62.java Tue Feb 12 19:25:09 2013 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007464 + * @summary Add graph inference support + * check that new wildcards inference strategy doesn't run into 7190296 + * @ignore awaits stream API: 800NNNN + * @compile TargetType62.java + */ +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +class TargetType61 { + + Collector test(Function classifier) { + return g(classifier, TreeMap::new, m(HashSet::new)); + } + + Collector m(Supplier s) { return null; } + + > + Collector g(Function classifier, Supplier mapFactory, Collector downstream) { return null; } +}