diff --git a/src/share/classes/com/sun/tools/javac/code/Types.java b/src/share/classes/com/sun/tools/javac/code/Types.java index e1acb125a029da70ebbf426f65137ed1574318af..7e168d85f31c4f3607c20c712becbb9035915c7c 100644 --- a/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/share/classes/com/sun/tools/javac/code/Types.java @@ -43,6 +43,7 @@ import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.code.Flags.*; @@ -305,8 +306,8 @@ public class Types { } /** - * Is t a subtype of or convertiable via boxing/unboxing - * convertions to s? + * Is t a subtype of or convertible via boxing/unboxing + * conversions to s? */ public boolean isConvertible(Type t, Type s) { return isConvertible(t, s, noWarnings); @@ -1934,6 +1935,17 @@ public class Types { * @param sym a symbol */ public Type asSuper(Type t, Symbol sym) { + /* Some examples: + * + * (Enum, Comparable) => Comparable + * (c.s.s.d.AttributeTree.ValueKind, Enum) => Enum + * (c.s.s.t.ExpressionTree, c.s.s.t.Tree) => c.s.s.t.Tree + * (j.u.List, Iterable) => + * Iterable + */ + if (sym.type == syms.objectType) { //optimization + return syms.objectType; + } return asSuper.visit(t, sym); } // where @@ -3869,9 +3881,11 @@ public class Types { } return buf.reverse(); } + public Type capture(Type t) { - if (!t.hasTag(CLASS)) + if (!t.hasTag(CLASS)) { return t; + } if (t.getEnclosingType() != Type.noType) { Type capturedEncl = capture(t.getEnclosingType()); if (capturedEncl != t.getEnclosingType()) { diff --git a/src/share/classes/com/sun/tools/javac/comp/Check.java b/src/share/classes/com/sun/tools/javac/comp/Check.java index 9ae4fcec7f10f2f19cae15c78ee3eb250f754153..5d7308dcdefe57300fa612e7a428901ad6208056 100644 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -510,6 +510,11 @@ public class Check { public DeferredAttrContext deferredAttrContext() { return deferredAttr.emptyDeferredAttrContext; } + + @Override + public String toString() { + return "CheckContext: basicHandler"; + } }; /** Check that a given type is assignable to a given proto-type. diff --git a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index bf3bd0c2d3e1d41b73cb4c0679d04ed7e11763ce..9ff8865f5f47ddb84f5fb72a0df0666f3b44d95c 100644 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -110,6 +110,11 @@ public class DeferredAttr extends JCTree.Visitor { void complete() { Assert.error("Empty deferred context!"); } + + @Override + public String toString() { + return "Empty deferred context!"; + } }; } diff --git a/src/share/classes/com/sun/tools/javac/comp/Infer.java b/src/share/classes/com/sun/tools/javac/comp/Infer.java index a7d5521487a19331b90c0d9fd3f4d7f0ff8c8a34..c2375e1488c92d004f3aa652a5e4d7c97cccb931 100644 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -142,24 +142,24 @@ public class Infer { * 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, - MethodType mt, - Attr.ResultInfo resultInfo, - Symbol msym, - List argtypes, - boolean allowBoxing, - boolean useVarargs, - Resolve.MethodResolutionContext resolveContext, - Warner warn) throws InferenceException { + Type instantiateMethod( Env env, + List tvars, + MethodType mt, + Attr.ResultInfo resultInfo, + MethodSymbol msym, + List argtypes, + boolean allowBoxing, + boolean useVarargs, + Resolve.MethodResolutionContext resolveContext, + Warner warn) throws InferenceException { //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG - final InferenceContext inferenceContext = new InferenceContext(tvars); + final InferenceContext inferenceContext = new InferenceContext(tvars); //B0 inferenceException.clear(); try { DeferredAttr.DeferredAttrContext deferredAttrContext = resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn); - resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, + resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext, //B2 argtypes, mt.getParameterTypes(), warn); if (allowGraphInference && @@ -167,7 +167,8 @@ public class Infer { !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { //inject return constraints earlier checkWithinBounds(inferenceContext, warn); //propagation - Type newRestype = generateReturnConstraints(resultInfo, mt, inferenceContext); + Type newRestype = generateReturnConstraints(env.tree, resultInfo, //B3 + mt, inferenceContext); mt = (MethodType)types.createMethodTypeWithReturn(mt, newRestype); //propagate outwards if needed if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { @@ -193,7 +194,7 @@ public class Infer { inferenceContext.restvars().nonEmpty() && resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) { - generateReturnConstraints(resultInfo, mt, inferenceContext); + generateReturnConstraints(env.tree, resultInfo, mt, inferenceContext); inferenceContext.solveLegacy(false, warn, LegacyInferenceSteps.EQ_UPPER.steps); //maximizeInst mt = (MethodType)inferenceContext.asInstType(mt); } @@ -210,6 +211,12 @@ public class Infer { } else { inferenceContext.notifyChange(inferenceContext.boundedVars()); } + if (resultInfo == null) { + /* if the is no result info then we can clear the capture types + * cache without affecting any result info check + */ + inferenceContext.captureTypeCache.clear(); + } } } @@ -218,7 +225,7 @@ public class Infer { * 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. */ - Type generateReturnConstraints(Attr.ResultInfo resultInfo, + Type generateReturnConstraints(JCTree tree, Attr.ResultInfo resultInfo, MethodType mt, InferenceContext inferenceContext) { InferenceContext rsInfoInfContext = resultInfo.checkContext.inferenceContext(); Type from = mt.getReturnType(); @@ -232,13 +239,29 @@ public class Infer { } } } - Type qtype1 = inferenceContext.asUndetVar(from); - Type to = returnConstraintTarget(qtype1, resultInfo.pt); + Type qtype = inferenceContext.asUndetVar(from); + Type to = resultInfo.pt; + + if (qtype.hasTag(VOID)) { + to = syms.voidType; + } else if (to.hasTag(NONE)) { + to = from.isPrimitive() ? from : syms.objectType; + } else if (qtype.hasTag(UNDETVAR)) { + if (resultInfo.pt.isReference()) { + to = generateReturnConstraintsUndetVarToReference( + tree, (UndetVar)qtype, to, resultInfo, inferenceContext); + } else { + if (to.isPrimitive()) { + to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to, + resultInfo, inferenceContext); + } + } + } Assert.check(allowGraphInference || !rsInfoInfContext.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, rsInfoInfContext.asUndetVar(to), retWarn) || + if (!resultInfo.checkContext.compatible(qtype, rsInfoInfContext.asUndetVar(to), retWarn) || //unchecked conversion is not allowed in source 7 mode (!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) { throw inferenceException @@ -248,30 +271,96 @@ public class Infer { return from; } - 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; + private Type generateReturnConstraintsPrimitive(JCTree tree, UndetVar from, + Type to, Attr.ResultInfo resultInfo, InferenceContext inferenceContext) { + if (!allowGraphInference) { + //if legacy, just return boxed type + return types.boxedClass(to).type; + } + //if graph inference we need to skip conflicting boxed bounds... + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.UPPER, + InferenceBound.LOWER)) { + Type boundAsPrimitive = types.unboxedType(t); + if (boundAsPrimitive == null || boundAsPrimitive.hasTag(NONE)) { + continue; + } + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + return types.boxedClass(to).type; + } + + private Type generateReturnConstraintsUndetVarToReference(JCTree tree, + UndetVar from, Type to, Attr.ResultInfo resultInfo, + InferenceContext inferenceContext) { + Type captureOfTo = types.capture(to); + /* T is a reference type, but is not a wildcard-parameterized type, and either + */ + if (captureOfTo == to) { //not a wildcard parameterized type + /* i) B2 contains a bound of one of the forms alpha = S or S <: alpha, + * where S is a wildcard-parameterized type, or + */ + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { + Type captureOfBound = types.capture(t); + if (captureOfBound != t) { + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + } + + /* ii) B2 contains two bounds of the forms S1 <: alpha and S2 <: alpha, + * where S1 and S2 have supertypes that are two different + * parameterizations of the same generic class or interface. + */ + for (Type aLowerBound : from.getBounds(InferenceBound.LOWER)) { + for (Type anotherLowerBound : from.getBounds(InferenceBound.LOWER)) { + if (aLowerBound != anotherLowerBound && + commonSuperWithDiffParameterization(aLowerBound, anotherLowerBound)) { + /* self comment check if any lower bound may be and undetVar, + * in that case the result of this call may be a false positive. + * Should this be restricted to non free types? + */ + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); + } + } + } + } + + /* T is a parameterization of a generic class or interface, G, + * and B2 contains a bound of one of the forms alpha = S or S <: alpha, + * where there exists no type of the form G<...> that is a + * supertype of S, but the raw type G is a supertype of S + */ + if (to.isParameterized()) { + for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) { + Type sup = types.asSuper(t, to.tsym); + if (sup != null && sup.isRaw()) { + return generateReferenceToTargetConstraint(tree, from, to, + resultInfo, inferenceContext); } } - return types.boxedClass(to).type; - } else { - return to; } + return to; + } + + private boolean commonSuperWithDiffParameterization(Type t, Type s) { + Pair supers = getParameterizedSupers(t, s); + return (supers != null && !types.isSameType(supers.fst, supers.snd)); + } + + private Type generateReferenceToTargetConstraint(JCTree tree, UndetVar from, + Type to, Attr.ResultInfo resultInfo, + InferenceContext inferenceContext) { + inferenceContext.solve(List.of(from.qtype), new Warner()); + Type capturedType = resultInfo.checkContext.inferenceContext() + .cachedCapture(tree, from.inst, false); + if (types.isConvertible(capturedType, + resultInfo.checkContext.inferenceContext().asUndetVar(to))) { + //effectively skip additional return-type constraint generation (compatibility) + return syms.objectType; + } + return to; } /** @@ -2082,8 +2171,10 @@ public class Infer { * 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); + that.inferencevars = that.inferencevars.appendList( + inferencevars.diff(that.inferencevars)); + that.undetvars = that.undetvars.appendList( + undetvars.diff(that.undetvars)); //set up listeners to notify original inference contexts as //propagated vars are inferred in new context for (Type t : inferencevars) { @@ -2202,6 +2293,30 @@ public class Infer { return "Inference vars: " + inferencevars + '\n' + "Undet vars: " + undetvars; } + + /* Method Types.capture() generates a new type every time it's applied + * to a wildcard parameterized type. This is intended functionality but + * there are some cases when what you need is not to generate a new + * captured type but to check that a previously generated captured type + * is correct. There are cases when caching a captured type for later + * reuse is sound. In general two captures from the same AST are equal. + * This is why the tree is used as the key of the map below. This map + * stores a Type per AST. + */ + Map captureTypeCache = new HashMap<>(); + + Type cachedCapture(JCTree tree, Type t, boolean readOnly) { + Type captured = captureTypeCache.get(tree); + if (captured != null) { + return captured; + } + + Type result = types.capture(t); + if (result != t && !readOnly) { // then t is a wildcard parameterized type + captureTypeCache.put(tree, result); + } + return result; + } } final InferenceContext emptyContext = new InferenceContext(List.nil()); diff --git a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index fd8ec17a7f4cb0b14bea435333f2a53dce335a87..e176e9288f9289d83f829fadefdb82f15b09791e 100644 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -36,6 +36,7 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; @@ -50,8 +51,10 @@ import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import java.util.EnumMap; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*; import static com.sun.tools.javac.code.Flags.*; @@ -438,13 +441,9 @@ public class LambdaToMethod extends TreeTranslator { public void visitVarDef(JCVariableDecl tree) { LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context; if (context != null && lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) { - JCExpression init = translate(tree.init); - int prevPos = make.pos; - try { - result = make.at(tree).VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym), init); - } finally { - make.at(prevPos); - } + tree.init = translate(tree.init); + tree.sym = (VarSymbol) lambdaContext.getSymbolMap(LOCAL_VAR).get(tree.sym); + result = tree; } else if (context != null && lambdaContext.getSymbolMap(TYPE_VAR).containsKey(tree.sym)) { JCExpression init = translate(tree.init); VarSymbol xsym = (VarSymbol)lambdaContext.getSymbolMap(TYPE_VAR).get(tree.sym); @@ -1286,7 +1285,10 @@ public class LambdaToMethod extends TreeTranslator { @Override public void visitNewClass(JCNewClass tree) { - if (lambdaNewClassFilter(context(), tree)) { + TypeSymbol def = tree.type.tsym; + boolean inReferencedClass = currentlyInClass(def); + boolean isLocal = def.isLocal(); + if ((inReferencedClass && isLocal || lambdaNewClassFilter(context(), tree))) { TranslationContext localContext = context(); while (localContext != null) { if (localContext.tree.getTag() == LAMBDA) { @@ -1296,16 +1298,16 @@ public class LambdaToMethod extends TreeTranslator { localContext = localContext.prev; } } - if (context() != null && tree.type.tsym.owner.kind == MTH) { + if (context() != null && !inReferencedClass && isLocal) { LambdaTranslationContext lambdaContext = (LambdaTranslationContext)context(); - captureLocalClassDefs(tree.type.tsym, lambdaContext); + captureLocalClassDefs(def, lambdaContext); } super.visitNewClass(tree); } //where void captureLocalClassDefs(Symbol csym, final LambdaTranslationContext lambdaContext) { JCClassDecl localCDef = localClassDefs.get(csym); - if (localCDef != null && localCDef.pos < lambdaContext.tree.pos) { + if (localCDef != null && lambdaContext.freeVarProcessedLocalClasses.add(csym)) { BasicFreeVarCollector fvc = lower.new BasicFreeVarCollector() { @Override void addFreeVars(ClassSymbol c) { @@ -1331,6 +1333,18 @@ public class LambdaToMethod extends TreeTranslator { fvc.scan(localCDef); } } + //where + boolean currentlyInClass(Symbol csym) { + for (Frame frame : frameStack) { + if (frame.tree.hasTag(JCTree.Tag.CLASSDEF)) { + JCClassDecl cdef = (JCClassDecl) frame.tree; + if (cdef.sym == csym) { + return true; + } + } + } + return false; + } /** * Method references to local class constructors, may, if the local @@ -1756,6 +1770,11 @@ public class LambdaToMethod extends TreeTranslator { List syntheticParams; + /** + * to prevent recursion, track local classes processed + */ + final Set freeVarProcessedLocalClasses; + LambdaTranslationContext(JCLambda tree) { super(tree); Frame frame = frameStack.head; @@ -1785,6 +1804,8 @@ public class LambdaToMethod extends TreeTranslator { translatedSymbols.put(CAPTURED_VAR, new LinkedHashMap()); translatedSymbols.put(CAPTURED_THIS, new LinkedHashMap()); translatedSymbols.put(TYPE_VAR, new LinkedHashMap()); + + freeVarProcessedLocalClasses = new HashSet<>(); } /** @@ -1895,7 +1916,7 @@ public class LambdaToMethod extends TreeTranslator { }; break; case LOCAL_VAR: - ret = new VarSymbol(sym.flags() & FINAL, name, types.erasure(sym.type), translatedSym); + ret = new VarSymbol(sym.flags() & FINAL, name, sym.type, translatedSym); ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; break; case PARAM: diff --git a/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/share/classes/com/sun/tools/javac/comp/Resolve.java index fd3abf5634a4fc1df8a38d97e5dcd1653ede35a8..e91869eb4f4f823268b71d47acc659e639a87a92 100644 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -565,7 +565,7 @@ public class Resolve { tvars, (MethodType)mt, resultInfo, - m, + (MethodSymbol)m, argtypes, allowBoxing, useVarargs, @@ -773,6 +773,7 @@ public class Resolve { public MethodCheck mostSpecificCheck(List actuals, boolean strict) { return nilMethodCheck; } + } /** @@ -784,6 +785,11 @@ public class Resolve { void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { //do nothing - actual always compatible to formals } + + @Override + public String toString() { + return "arityMethodCheck"; + } }; List dummyArgs(int length) { @@ -869,6 +875,11 @@ public class Resolve { public MethodCheck mostSpecificCheck(List actuals, boolean strict) { return new MostSpecificCheck(strict, actuals); } + + @Override + public String toString() { + return "resolveMethodCheck"; + } }; /** @@ -900,7 +911,9 @@ public class Resolve { @Override public boolean compatible(Type found, Type req, Warner warn) { found = pendingInferenceContext.asUndetVar(found); - req = infer.returnConstraintTarget(found, req); + if (found.hasTag(UNDETVAR) && req.isPrimitive()) { + req = types.boxedClass(req).type; + } return super.compatible(found, req, warn); } @@ -955,6 +968,12 @@ public class Resolve { public DeferredAttrContext deferredAttrContext() { return deferredAttrContext; } + + @Override + public String toString() { + return "MethodReferenceCheck"; + } + } /** @@ -973,7 +992,12 @@ public class Resolve { DeferredType dt = (DeferredType)found; return dt.check(this); } else { - return super.check(pos, chk.checkNonVoid(pos, types.capture(U(found.baseType())))); + Type uResult = U(found.baseType()); + Type capturedType = pos == null || pos.getTree() == null ? + types.capture(uResult) : + checkContext.inferenceContext() + .cachedCapture(pos.getTree(), uResult, true); + return super.check(pos, chk.checkNonVoid(pos, capturedType)); } } diff --git a/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTesta.java b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTesta.java new file mode 100644 index 0000000000000000000000000000000000000000..860a95987bece8c2d676e56386c9da9551776331 --- /dev/null +++ b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTesta.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, 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. + */ + +/* + * @test + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile EagerReturnTypeResolutionTesta.java + */ + +public class EagerReturnTypeResolutionTesta { + + abstract class Test1{ + abstract S foo(S x, S y); + > void baz(Test1 a){} + + void bar(Test1 x, Test1 y){ + baz(foo(x, y)); + } + } + + abstract class Test2{ + abstract S foo(S x, S y); + abstract void baz(Test2 a); + + void bar(Test2 y, Test2 x){ + baz(foo(x, y)); + } + } + + abstract class Test3{ + abstract S foo(S x, S y); + , + S extends Number & Comparable> void baz(Test3 a){} + + void bar(Test3 x, Test3 y){ + baz(foo(x, y)); + } + } + + abstract class Test4 { + abstract class A0 {} + + abstract class A1 extends A0 {} + + abstract class A2 extends A0 {} + + abstract S foo(S x, S y); + abstract void baz(A0 a); + + void bar(A2 y, A1 x){ + baz(foo(x, y)); + } + } + +} diff --git a/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.java b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.java new file mode 100644 index 0000000000000000000000000000000000000000..959d5eb34efca9d0720a97beb7ede3daff70a083 --- /dev/null +++ b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.java @@ -0,0 +1,182 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile/fail/ref=EagerReturnTypeResolutionTestb.out -XDrawDiagnostics EagerReturnTypeResolutionTestb.java + * @author Dan Smith + */ + +import java.util.List; + +public class EagerReturnTypeResolutionTestb { + interface I {} + interface J extends I {} + interface K extends I {} + interface L extends I {} + + T lower(List l) { return null; } + T lower2(List l1, List l2) { return null; } + + T upper(List l) { return null; } + T upper2(List l1, List l2) { return null; } + + T eq(List l) { return null; } + T eq2(List l1, List l2) { return null; } + + void takeI(I i) {} + void takeIString(I i) {} + I iStringField; + + void takeLong(long arg) {} + long longField; + + void testSimpleCaptureOK(List> i1) { + takeI(lower(i1)); // ok* + takeI(eq(i1)); // ok* + takeI(upper(i1)); // ok, no capture + takeIString(upper(i1)); // ok + iStringField = upper(i1); // ok + } + + void testSimpleCaptureKO(List> i1) { + takeIString(lower(i1)); // ERROR + takeIString(eq(i1)); // ERROR + iStringField = lower(i1); // ERROR + iStringField = eq(i1); // ERROR + } + + void testMultiCaptureOK(List> i1, List> i2, List> i3, + List> j1, List> j2, List k1) { + /* Lines marked with JDK-8029002 should be uncommented once this bug is + * fixed + */ + takeI(lower2(i1, i2)); // ok* + takeI(lower2(i1, i3)); // ok* + takeI(upper2(i1, i3)); // ok, no capture* JDK-8029002 + + takeIString(upper2(i1, i3)); // ok, no capture + iStringField = upper2(i1, i3); // ok, no capture + + takeI(lower2(j1, j2)); // ok* + takeI(lower2(j1, k1)); // ok, no capture + takeI(upper2(j1, k1)); // ok, no capture* JDK-8029002 + + takeIString(lower2(j1, k1)); // ok, no capture + takeIString(upper2(j1, k1)); // ok, no capture + + iStringField = lower2(j1, k1); // ok, no capture + iStringField = upper2(j1, k1); // ok, no capture + takeI(lower2(j2, k1)); // ok* + } + + void testMultiCaptureKO(List> i1, List> i2, List> i3, + List> j1, List> j2, List k1) { + takeI(eq2(i1, i2)); // ERROR, bad bounds + takeI(upper2(i1, i2)); // ERROR, bad bounds + + takeIString(lower2(i1, i2)); // ERROR + takeIString(eq2(i1, i2)); // ERROR, bad bounds + takeIString(upper2(i1, i2)); // ERROR, bad bounds + + iStringField = lower2(i1, i2); // ERROR + iStringField = eq2(i1, i2); // ERROR, bad bounds + iStringField = upper2(i1, i2); // ERROR, bad bounds + + takeI(eq2(i1, i3)); // ERROR, bad bounds + takeIString(lower2(i1, i3)); // ERROR + takeIString(eq2(i1, i3)); // ERROR, bad bounds + + iStringField = lower2(i1, i3); // ERROR + iStringField = eq2(i1, i3); // ERROR, bad bounds + takeI(eq2(j1, j2)); // ERROR, bad bounds + takeI(upper2(j1, j2)); // ERROR, bad bounds + + takeIString(lower2(j1, j2)); // ERROR + takeIString(eq2(j1, j2)); // ERROR, bad bounds + takeIString(upper2(j1, j2)); // ERROR, bad bounds + + iStringField = lower2(j1, j2); // ERROR + iStringField = eq2(j1, j2); // ERROR, bad bounds + iStringField = upper2(j1, j2); // ERROR, bad bounds + + takeI(eq2(j1, k1)); // ERROR, bad bounds + takeIString(eq2(j1, k1)); // ERROR, bad bounds + iStringField = eq2(j1, k1); // ERROR, bad bounds + takeI(eq2(j2, k1)); // ERROR, bad bounds + takeI(upper2(j2, k1)); // ERROR, bad bounds; actual: no error, see JDK-8037474 + + takeIString(lower2(j2, k1)); // ERROR + takeIString(eq2(j2, k1)); // ERROR, bad bounds + takeIString(upper2(j2, k1)); // ERROR, bad bounds + + iStringField = lower2(j2, k1); // ERROR + iStringField = eq2(j2, k1); // ERROR, bad bounds + iStringField = upper2(j2, k1); // ERROR, bad bounds + } + + void testRawOK(List i1, List j1, List> l1) { + takeI(lower(i1)); // ok, unchecked + takeI(eq(i1)); // ok, unchecked + takeI(upper(i1)); // ok, no capture, not unchecked + + takeIString(lower(i1)); // ok, unchecked + takeIString(eq(i1)); // ok, unchecked + takeIString(upper(i1)); // ok, no capture, not unchecked + + iStringField = lower(i1); // ok, unchecked + iStringField = eq(i1); // ok, unchecked + iStringField = upper(i1); // ok, no capture, not unchecked + + takeI(lower(j1)); // ok, unchecked + takeI(eq(j1)); // ok, unchecked + takeI(upper(j1)); // bad bounds? -- spec is unclear + + takeIString(lower(j1)); // ok, unchecked + takeIString(eq(j1)); // ok, unchecked + takeIString(upper(j1)); // bad bounds? -- spec is unclear + + iStringField = lower(j1); // ok, unchecked + iStringField = eq(j1); // ok, unchecked + iStringField = upper(j1); // bad bounds? -- spec is unclear + + takeI(lower(l1)); // ok, unchecked + takeI(eq(l1)); // ok, unchecked + takeI(upper(l1)); // bad bounds? -- spec is unclear + + takeIString(lower(l1)); // ok, unchecked + takeIString(eq(l1)); // ok, unchecked + takeIString(upper(l1)); // bad bounds? -- spec is unclear + + iStringField = lower(l1); // ok, unchecked + iStringField = eq(l1); // ok, unchecked + iStringField = upper(l1); // bad bounds? -- spec is unclear + } + + void testPrimOK(List i1, List l1, List d1) { + takeLong(lower(i1)); // ok + takeLong(eq(i1)); // ok + takeLong(upper(i1)); // ok* + + longField = lower(i1); // ok + longField = eq(i1); // ok + longField = upper(i1); // ok* + + takeLong(lower(l1)); // ok + takeLong(eq(l1)); // ok + takeLong(upper(l1)); // ok + + longField = lower(l1); // ok + longField = eq(l1); // ok + longField = upper(l1); // ok + } + + void testPrimKO(List i1, List l1, List d1) { + takeLong(lower(d1)); // ERROR + takeLong(eq(d1)); // ERROR + takeLong(upper(d1)); // ERROR + + longField = lower(d1); // ERROR + longField = eq(d1); // ERROR + longField = upper(d1); // ERROR + } +} diff --git a/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out new file mode 100644 index 0000000000000000000000000000000000000000..52b1702f12a966d763fbcb50b793629eee665c52 --- /dev/null +++ b/test/tools/javac/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out @@ -0,0 +1,45 @@ +EagerReturnTypeResolutionTestb.java:42:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:43:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:44:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:45:26: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:74:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:75:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:77:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:78:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:79:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:81:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:82:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:83:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:85:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:86:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:87:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:89:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:90:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) +EagerReturnTypeResolutionTestb.java:91:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:92:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:94:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.J>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:95:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:96:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:98:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:99:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:100:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:102:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:103:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:104:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:105:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:106:9: compiler.err.cant.apply.symbol: kindname.method, takeI, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Integer, java.lang.Integer,java.lang.String) +EagerReturnTypeResolutionTestb.java:108:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:109:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:110:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:112:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:113:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) +EagerReturnTypeResolutionTestb.java:114:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:174:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:175:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:176:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) +EagerReturnTypeResolutionTestb.java:178:26: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +EagerReturnTypeResolutionTestb.java:179:23: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +EagerReturnTypeResolutionTestb.java:180:26: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.instance.exists: , T, long) +- compiler.note.unchecked.filename: EagerReturnTypeResolutionTestb.java +- compiler.note.unchecked.recompile +42 errors diff --git a/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.java b/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b300a158c7e94eb050fa796d586d4d46e8eedd19 --- /dev/null +++ b/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.java @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8030741 + * @summary Inference: implement eager resolution of return types, consistent with JDK-8028800 + * @compile/fail/ref=PrimitiveTypeBoxingTest.out -XDrawDiagnostics PrimitiveTypeBoxingTest.java + */ + +public class PrimitiveTypeBoxingTest { + + static void foo(long arg) {} + static void bar(int arg) {} + + interface F { void get(X arg); } + + void m1(F f, Z arg) {} + void m2(Z arg, F f) {} + + void test() { + m1(PrimitiveTypeBoxingTest::foo, 23); // expected: error + m2(23, PrimitiveTypeBoxingTest::foo); // expected: error + + m1(PrimitiveTypeBoxingTest::bar, 23); // expected: success + m2(23, PrimitiveTypeBoxingTest::bar); // expected: success + } +} diff --git a/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out b/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out new file mode 100644 index 0000000000000000000000000000000000000000..ed15351e31b2197d3d2b8a56777a43fcae228680 --- /dev/null +++ b/test/tools/javac/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out @@ -0,0 +1,3 @@ +PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F,Z, @490,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.Long,java.lang.Object) +PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F, int,@559, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.Long,java.lang.Object) +2 errors diff --git a/test/tools/javac/lambda/LambdaLocalTest.java b/test/tools/javac/lambda/LambdaLocalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1b93ca5e301b5020497f13c49c5d795384e7b2ab --- /dev/null +++ b/test/tools/javac/lambda/LambdaLocalTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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 8029725 + * @summary Lambda reference to containing local class causes javac infinite recursion + * @author Robert Field + * @run main LambdaLocalTest + */ + +public class LambdaLocalTest { + interface F {void f();} + + static F f; + static StringBuffer sb = new StringBuffer(); + + static void assertEquals(Object val, Object expected) { + if (!val.equals(expected)) { + throw new AssertionError("expected '" + expected + "' got '" + val + "'"); + } + } + + public static void main(String[] args) { + class Local { + public Local() { + f = () -> new Local(); + sb.append("+"); + } + } + new Local(); + f.f(); + assertEquals(sb.toString(), "++"); + } +} diff --git a/test/tools/javac/lambda/LambdaMultiCatchTest.java b/test/tools/javac/lambda/LambdaMultiCatchTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f6ff58637828b39de242bc080f3b2c3947fe733b --- /dev/null +++ b/test/tools/javac/lambda/LambdaMultiCatchTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8036942 + * @summary javac generates incorrect exception table for multi-catch statements inside a lambda + * @run main LambdaMultiCatchTest + */ + +import java.io.IOException; +import java.util.function.Function; + +public class LambdaMultiCatchTest { + public static void main(String[] args) { + Function fi = x -> { + String result = "nada"; + try { + switch (x) { + case "IO": throw new IOException(); + case "Illegal": throw new IllegalArgumentException(); + case "Run": throw new RuntimeException(); + } + } catch (IOException|IllegalArgumentException ex) { + result = "IO/Illegal"; + } catch (Exception ex) { + result = "Any"; + }; + return result; + }; + String val = fi.apply("Run"); + if (!val.equals("Any")) { + throw new AssertionError("Fail: Expected 'Any' but got '" + val + "'"); + } + } +} diff --git a/test/tools/javac/lambda/LambdaOuterLocalTest.java b/test/tools/javac/lambda/LambdaOuterLocalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..63f4a896fa6d82fde746875ef95fea512dbddf71 --- /dev/null +++ b/test/tools/javac/lambda/LambdaOuterLocalTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, 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 8029725 + * @summary Lambda reference to containing local class causes javac infinite recursion + * @author Robert Field + * @run main LambdaOuterLocalTest + */ + +public class LambdaOuterLocalTest { + interface F {void f();} + + static F f; + static StringBuffer sb = new StringBuffer(); + + static void assertEquals(Object val, Object expected) { + if (!val.equals(expected)) { + throw new AssertionError("expected '" + expected + "' got '" + val + "'"); + } + } + + public static void main(String[] args) { + class Local1 { + public Local1() { + class Local2 { + public Local2() { + f = () -> new Local1(); + sb.append("2"); + } + } + sb.append("1"); + new Local2(); + } + } + new Local1(); + f.f(); + assertEquals(sb.toString(), "1212"); + } +} diff --git a/test/tools/javac/lambda/SingleLocalTest.java b/test/tools/javac/lambda/SingleLocalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b67a4d6ce62c561b09021f67c77affbda12bce3f --- /dev/null +++ b/test/tools/javac/lambda/SingleLocalTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 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 8029852 + * @summary Bad code generated (VerifyError) when lambda instantiates + * enclosing local class and has captured variables + */ +public class SingleLocalTest { + interface F {void f();} + + static F f; + + public static void main(String[] args) { + StringBuffer sb = new StringBuffer(); + class Local1 { + public Local1() { + f = () -> new Local1(); + sb.append("1"); + } + } + new Local1(); + f.f(); + String s = sb.toString(); + if (!s.equals("11")) { + throw new AssertionError("Expected '11' got '" + s + "'"); + } + } +}