Mercurial > hg > openjdk > lambda > langtools
changeset 2245:00274133b7d2
8016177: structural most specific and stuckness
8016178: Order of unsticking functional expressions
Refined rules for structural most specific for lambda/method references after recent changes.
author | mcimadamore |
---|---|
date | Fri, 26 Jul 2013 12:46:37 +0100 |
parents | d34073d069c8 |
children | 93e9a9aa6e18 |
files | src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/tree/JCTree.java test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java test/tools/javac/lambda/8016177/T8016177c.java test/tools/javac/lambda/8016177/T8016177c.out test/tools/javac/lambda/methodReference/SamConversionComboTest.java |
diffstat | 7 files changed, 104 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Jul 25 16:29:24 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Fri Jul 26 12:46:37 2013 +0100 @@ -25,6 +25,7 @@ package com.sun.tools.javac.comp; +import com.sun.source.tree.MemberReferenceTree; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; @@ -553,10 +554,12 @@ ResultInfo resultInfo; InferenceContext inferenceContext; + Env<AttrContext> env; public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { this.resultInfo = resultInfo; this.inferenceContext = deferredAttrContext.inferenceContext; + this.env = dt.env; dt.tree.accept(this); dt.speculativeCache.put(stuckTree, resultInfo); return Type.noType; @@ -605,7 +608,19 @@ } catch (Types.FunctionDescriptorLookupError ex) { checkContext.report(null, ex.getDiagnostic()); } - switch (tree.sym.kind) { + Env<AttrContext> localEnv = env.dup(tree); + JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, + attr.memberReferenceQualifierResult(tree)); + ListBuffer<Type> argtypes = ListBuffer.lb(); + for (Type t : types.findDescriptorType(pt).getParameterTypes()) { + argtypes.append(Type.noType); + } + JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); + mref2.expr = exprTree; + Pair<Symbol, ?> lookupRes = + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, + tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext); + switch (lookupRes.fst.kind) { //note: as argtypes are erroneous types, type-errors must //have been caused by arity mismatch case Kinds.ABSENT_MTH: @@ -847,30 +862,10 @@ Type descType = types.findDescriptorType(pt); List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); - Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); - if (freeArgVars.nonEmpty()) { - //perform arity-based check - JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, - attr.memberReferenceQualifierResult(tree)); - ListBuffer<Type> argtypes = ListBuffer.lb(); - for (Type t : descType.getParameterTypes()) { - argtypes.append(Type.noType); - } - JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); - mref2.expr = exprTree; - Pair<Symbol, ReferenceLookupHelper> lookupRes = - rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, - tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, - inferenceContext); - Symbol res = tree.sym = lookupRes.fst; - if (res.kind >= Kinds.ERRONEOUS || - res.type.hasTag(FORALL) || - (res.flags() & Flags.VARARGS) != 0 || - (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && - exprTree.type.isRaw())) { - stuckVars.addAll(freeArgVars); - depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); - } + if (freeArgVars.nonEmpty() && + tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) { + stuckVars.addAll(freeArgVars); + depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); } } @@ -978,6 +973,26 @@ @Override public void visitReference(JCMemberReference tree) { + //perform arity-based check + Env<AttrContext> localEnv = env.dup(tree); + JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, + attr.memberReferenceQualifierResult(tree)); + JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree); + mref2.expr = exprTree; + Pair<Symbol, ReferenceLookupHelper> lookupRes = + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, + tree.name, List.<Type>nil(), null, true, rs.nilMethodCheck, + infer.emptyContext); + Symbol res = tree.sym = lookupRes.fst; + if (res.kind >= Kinds.ERRONEOUS || + res.type.hasTag(FORALL) || + (res.flags() & Flags.VARARGS) != 0 || + (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && + exprTree.type.isRaw())) { + tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; + } else { + tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; + } //a method reference is always a poly expression result = ArgumentExpressionKind.POLY; }
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jul 25 16:29:24 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Jul 26 12:46:37 2013 +0100 @@ -1064,7 +1064,7 @@ return (e1 == null || e2 == null || e1.speculativeTree == deferredAttr.stuckTree || e2.speculativeTree == deferredAttr.stuckTree) ? - super.compatible(found, req, warn) : + false : mostSpecific(e2.resultInfo.pt, patchPt(e1), e1.speculativeTree, warn); default: return standaloneMostSpecific(found, req, actual, warn); @@ -1151,13 +1151,15 @@ @Override public void visitReference(JCMemberReference tree) { if (types.isFunctionalInterface(t.tsym) && - types.isFunctionalInterface(s.tsym) && - types.asSuper(t, s.tsym) == null && - types.asSuper(s, t.tsym) == null) { + types.isFunctionalInterface(s.tsym)) { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); - if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { - if (!desc_s.getReturnType().hasTag(VOID)) { + if (types.isSameTypes(desc_t.getParameterTypes(), + inferenceContext().asFree(desc_s.getParameterTypes()))) { + if (types.asSuper(t, s.tsym) != null || + types.asSuper(s, t.tsym) != null) { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } else if (!desc_s.getReturnType().hasTag(VOID)) { //perform structural comparison Type ret_t = desc_t.getReturnType(); Type ret_s = desc_s.getReturnType(); @@ -1167,25 +1169,24 @@ } else { return; } - } else { - result &= false; } } else { - result &= MostSpecificCheckContext.super.compatible(t, s, warn); + result &= false; } } @Override public void visitLambda(JCLambda tree) { if (types.isFunctionalInterface(t.tsym) && - types.isFunctionalInterface(s.tsym) && - types.asSuper(t, s.tsym) == null && - types.asSuper(s, t.tsym) == null) { + types.isFunctionalInterface(s.tsym)) { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); - if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT - || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { - if (!desc_s.getReturnType().hasTag(VOID)) { + if (types.isSameTypes(desc_t.getParameterTypes(), + inferenceContext().asFree(desc_s.getParameterTypes()))) { + if (types.asSuper(t, s.tsym) != null || + types.asSuper(s, t.tsym) != null) { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } else if (!desc_s.getReturnType().hasTag(VOID)) { //perform structural comparison Type ret_t = desc_t.getReturnType(); Type ret_s = desc_s.getReturnType(); @@ -1193,11 +1194,9 @@ } else { return; } - } else { - result &= false; } } else { - result &= MostSpecificCheckContext.super.compatible(t, s, warn); + result &= false; } } //where
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jul 25 16:29:24 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Jul 26 12:46:37 2013 +0100 @@ -1898,6 +1898,7 @@ * Selects a member expression. */ public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree { + public ReferenceMode mode; public ReferenceKind kind; public Name name; @@ -1907,6 +1908,12 @@ public Type varargsElement; public PolyKind refPolyKind; public boolean ownerAccessible; + public OverloadKind overloadKind; + + public enum OverloadKind { + OVERLOADED, + UNOVERLOADED; + } /** * Javac-dependent classification for member references, based
--- a/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java Thu Jul 25 16:29:24 2013 +0100 +++ b/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java Fri Jul 26 12:46:37 2013 +0100 @@ -31,6 +31,7 @@ } void g(String s, Integer i) { } + void g(Integer i, String s) { } <Z> void m(SAM<Z> s) { }
--- a/test/tools/javac/lambda/8016177/T8016177c.java Thu Jul 25 16:29:24 2013 +0100 +++ b/test/tools/javac/lambda/8016177/T8016177c.java Fri Jul 26 12:46:37 2013 +0100 @@ -1,31 +1,8 @@ /* - * 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 + * @test /nodynamiccopyright/ * @bug 8016081 8016178 * @summary structural most specific and stuckness - * @compile T8016177c.java + * @compile/fail/ref=T8016177c.out -XDrawDiagnostics T8016177c.java */ class T8016177c { @@ -36,8 +13,35 @@ interface ExtFunction<X, Y> extends Function<X, Y> { } - <U, V> U m(Function<U, V> f) { return null; } - <U, V> U m(ExtFunction<U, V> f) { return null; } + <U, V> U m1(Function<U, V> f) { return null; } + <U, V> U m1(ExtFunction<U, V> f) { return null; } + + void m2(Function<Integer, Integer> f) { } + void m2(ExtFunction<Integer, Integer> f) { } + + void m3(Function<Integer, Integer> f) { } + void m3(ExtFunction<Object, Integer> f) { } + + int g1(Object s) { return 1; } + + int g2(Number s) { return 1; } + int g2(Object s) { return 1; } - void test() { m(x->1); } + void test() { + m1((Integer x)->x); //ok - explicit lambda - subtyping picks most specific + m2((Integer x)->x); //ok - explicit lambda - subtyping picks most specific + m3((Integer x)->x); //ok - explicit lambda (only one applicable) + + m1(x->1); //ambiguous - stuck lambda + m2(x->1); //ok - subtyping picks most specific + m3(x->1); //ambiguous - implicit lambda & different params + + m1(this::g1); //ok - unambiguous ref - subtyping picks most specific + m2(this::g1); //ok - unambiguous ref - subtyping picks most specific + m3(this::g1); //ambiguous - both applicable, neither most specific + + m1(this::g2); //ambiguous - stuck mref + m2(this::g2); //ok - subtyping picks most specific + m3(this::g2); //ambiguous - different params + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/8016177/T8016177c.out Fri Jul 26 12:46:37 2013 +0100 @@ -0,0 +1,6 @@ +T8016177c.java:35:9: compiler.err.ref.ambiguous: m1, kindname.method, <U,V>m1(T8016177c.Function<U,V>), T8016177c, kindname.method, <U,V>m1(T8016177c.ExtFunction<U,V>), T8016177c +T8016177c.java:37:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c +T8016177c.java:41:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c +T8016177c.java:43:9: compiler.err.ref.ambiguous: m1, kindname.method, <U,V>m1(T8016177c.Function<U,V>), T8016177c, kindname.method, <U,V>m1(T8016177c.ExtFunction<U,V>), T8016177c +T8016177c.java:45:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function<java.lang.Integer,java.lang.Integer>), T8016177c, kindname.method, m3(T8016177c.ExtFunction<java.lang.Object,java.lang.Integer>), T8016177c +5 errors
--- a/test/tools/javac/lambda/methodReference/SamConversionComboTest.java Thu Jul 25 16:29:24 2013 +0100 +++ b/test/tools/javac/lambda/methodReference/SamConversionComboTest.java Fri Jul 26 12:46:37 2013 +0100 @@ -7,7 +7,7 @@ * 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 + * ANY WARRANTY; without even the implied warranty of MERzCHANTABILITY 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).