Fri, 20 Jun 2014 20:36:54 +0100
8044546: Crash on faulty reduce/lambda
Reviewed-by: mcimadamore, dlsmith
Contributed-by: maurizio.cimadamore@oracle.com, vicente.romero@oracle.com
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu Jul 17 10:55:50 2014 -0400 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Fri Jun 20 20:36:54 2014 +0100 1.3 @@ -2954,6 +2954,12 @@ 1.4 } 1.5 1.6 @Override 1.7 + public Type visitUndetVar(UndetVar t, Void ignored) { 1.8 + //do nothing - we should not replace inside undet variables 1.9 + return t; 1.10 + } 1.11 + 1.12 + @Override 1.13 public Type visitClassType(ClassType t, Void ignored) { 1.14 if (!t.isCompound()) { 1.15 List<Type> typarams = t.getTypeArguments();
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 17 10:55:50 2014 -0400 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Jun 20 20:36:54 2014 +0100 2.3 @@ -252,36 +252,30 @@ 2.4 */ 2.5 Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) { 2.6 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 2.7 - Type owntype = found; 2.8 - if (!owntype.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) { 2.9 - if (allowPoly && inferenceContext.free(found)) { 2.10 - if ((ownkind & ~resultInfo.pkind) == 0) { 2.11 - owntype = resultInfo.check(tree, inferenceContext.asUndetVar(owntype)); 2.12 - } else { 2.13 - log.error(tree.pos(), "unexpected.type", 2.14 - kindNames(resultInfo.pkind), 2.15 - kindName(ownkind)); 2.16 - owntype = types.createErrorType(owntype); 2.17 - } 2.18 + Type owntype; 2.19 + if (!found.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) { 2.20 + if ((ownkind & ~resultInfo.pkind) != 0) { 2.21 + log.error(tree.pos(), "unexpected.type", 2.22 + kindNames(resultInfo.pkind), 2.23 + kindName(ownkind)); 2.24 + owntype = types.createErrorType(found); 2.25 + } else if (allowPoly && inferenceContext.free(found)) { 2.26 + //delay the check if there are inference variables in the found type 2.27 + //this means we are dealing with a partially inferred poly expression 2.28 + owntype = resultInfo.pt; 2.29 inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { 2.30 @Override 2.31 public void typesInferred(InferenceContext inferenceContext) { 2.32 ResultInfo pendingResult = 2.33 - resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 2.34 + resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 2.35 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); 2.36 } 2.37 }); 2.38 - return tree.type = resultInfo.pt; 2.39 } else { 2.40 - if ((ownkind & ~resultInfo.pkind) == 0) { 2.41 - owntype = resultInfo.check(tree, owntype); 2.42 - } else { 2.43 - log.error(tree.pos(), "unexpected.type", 2.44 - kindNames(resultInfo.pkind), 2.45 - kindName(ownkind)); 2.46 - owntype = types.createErrorType(owntype); 2.47 - } 2.48 + owntype = resultInfo.check(tree, found); 2.49 } 2.50 + } else { 2.51 + owntype = found; 2.52 } 2.53 tree.type = owntype; 2.54 return owntype; 2.55 @@ -2335,6 +2329,7 @@ 2.56 currentTarget = infer.instantiateFunctionalInterface(that, 2.57 currentTarget, explicitParamTypes, resultInfo.checkContext); 2.58 } 2.59 + currentTarget = types.removeWildcards(currentTarget); 2.60 lambdaType = types.findDescriptorType(currentTarget); 2.61 } else { 2.62 currentTarget = Type.recoveryType; 2.63 @@ -2727,7 +2722,7 @@ 2.64 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 2.65 isSerializable(currentTarget); 2.66 if (currentTarget != Type.recoveryType) { 2.67 - currentTarget = targetChecker.visit(currentTarget, that); 2.68 + currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that)); 2.69 desc = types.findDescriptorType(currentTarget); 2.70 } else { 2.71 currentTarget = Type.recoveryType;
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Jul 17 10:55:50 2014 -0400 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Jun 20 20:36:54 2014 +0100 3.3 @@ -531,8 +531,8 @@ 3.4 3.5 Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) { 3.6 final Infer.InferenceContext inferenceContext = checkContext.inferenceContext(); 3.7 - if (inferenceContext.free(req)) { 3.8 - inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() { 3.9 + if (inferenceContext.free(req) || inferenceContext.free(found)) { 3.10 + inferenceContext.addFreeTypeListener(List.of(req, found), new FreeTypeListener() { 3.11 @Override 3.12 public void typesInferred(InferenceContext inferenceContext) { 3.13 checkType(pos, inferenceContext.asInstType(found), inferenceContext.asInstType(req), checkContext);
4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Thu Jul 17 10:55:50 2014 -0400 4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Jun 20 20:36:54 2014 +0100 4.3 @@ -353,6 +353,7 @@ 4.4 Type to, Attr.ResultInfo resultInfo, 4.5 InferenceContext inferenceContext) { 4.6 inferenceContext.solve(List.of(from.qtype), new Warner()); 4.7 + inferenceContext.notifyChange(); 4.8 Type capturedType = resultInfo.checkContext.inferenceContext() 4.9 .cachedCapture(tree, from.inst, false); 4.10 if (types.isConvertible(capturedType, 4.11 @@ -449,7 +450,7 @@ 4.12 class ImplicitArgType extends DeferredAttr.DeferredTypeMap { 4.13 4.14 public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) { 4.15 - rs.deferredAttr.super(AttrMode.SPECULATIVE, msym, phase); 4.16 + (rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase); 4.17 } 4.18 4.19 public Type apply(Type t) { 4.20 @@ -517,6 +518,8 @@ 4.21 //or if it's not a subtype of the original target, issue an error 4.22 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface)); 4.23 } 4.24 + //propagate constraints as per JLS 18.2.1 4.25 + checkContext.compatible(owntype, funcInterface, types.noWarnings); 4.26 return owntype; 4.27 } 4.28 }
5.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jul 17 10:55:50 2014 -0400 5.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Jun 20 20:36:54 2014 +0100 5.3 @@ -957,9 +957,10 @@ 5.4 } 5.5 5.6 public boolean compatible(Type found, Type req, Warner warn) { 5.7 + InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 5.8 return strict ? 5.9 - types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn) : 5.10 - types.isConvertible(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn); 5.11 + types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) : 5.12 + types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn); 5.13 } 5.14 5.15 public void report(DiagnosticPosition pos, JCDiagnostic details) {
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/generics/inference/T8044546/CrashImplicitLambdaTest.java Fri Jun 20 20:36:54 2014 +0100 6.3 @@ -0,0 +1,41 @@ 6.4 +/* 6.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/** 6.28 + * @test 6.29 + * @bug 8044546 6.30 + * @summary Crash on faulty reduce/lambda 6.31 + * @compile CrashImplicitLambdaTest.java 6.32 + */ 6.33 + 6.34 +abstract class CrashImplicitLambdaTest { 6.35 + boolean foo() { 6.36 + return bar(true, a -> {}); 6.37 + } 6.38 + 6.39 + abstract <T1> T1 bar(T1 t1, S<T1> s); 6.40 + 6.41 + interface S<S1> { 6.42 + void baz(S1 s1); 6.43 + } 6.44 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/generics/inference/T8044546/NestedInvocationsTest.java Fri Jun 20 20:36:54 2014 +0100 7.3 @@ -0,0 +1,47 @@ 7.4 +/* 7.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +/** 7.28 + * @test 7.29 + * @bug 8044546 7.30 + * @summary Crash on faulty reduce/lambda 7.31 + * @compile NestedInvocationsTest.java 7.32 + */ 7.33 + 7.34 +class NestedInvocationsTest<T> { 7.35 + boolean foo(I<T> i) { 7.36 + return baz(zas(i)); 7.37 + } 7.38 + 7.39 + <U> J<U, Boolean> zas(I<U> i) { 7.40 + return null; 7.41 + } 7.42 + 7.43 + <R> R baz(J<T, R> j) { 7.44 + return null; 7.45 + } 7.46 + 7.47 + interface I<I1> {} 7.48 + 7.49 + interface J<J1, J2> {} 7.50 +}