8203488: Remove error generation from TransTypes

Bridge clash errors should noty be reported in TransTypes (as they are already reported in the frontend); cleanup polysig call code.

Reviewed-by: vromero, cushon, forax
This commit is contained in:
Maurizio Cimadamore 2018-05-24 11:13:42 +01:00
parent a7ac132ac4
commit d10e29af44
14 changed files with 211 additions and 145 deletions

View File

@ -3004,7 +3004,7 @@ public class Attr extends JCTree.Visitor {
List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
try {
refResult = rs.resolveMemberReference(localEnv, that, that.expr.type,
that.name, argtypes, typeargtypes, referenceCheck,
that.name, argtypes, typeargtypes, targetInfo.descriptor, referenceCheck,
resultInfo.checkContext.inferenceContext(), rs.basicReferenceChooser);
} finally {
resultInfo.checkContext.inferenceContext().rollback(saved_undet);
@ -3060,7 +3060,7 @@ public class Attr extends JCTree.Visitor {
}
}
that.sym = refSym.baseSymbol();
that.sym = refSym.isConstructor() ? refSym.baseSymbol() : refSym;
that.kind = lookupHelper.referenceKind(that.sym);
that.ownerAccessible = rs.isAccessible(localEnv, that.sym.enclClass());
@ -3798,33 +3798,10 @@ public class Attr extends JCTree.Visitor {
Env<AttrContext> env,
ResultInfo resultInfo) {
return (resultInfo.pt.hasTag(FORALL) || resultInfo.pt.hasTag(METHOD)) ?
checkMethodId(tree, site, sym, env, resultInfo) :
checkMethodIdInternal(tree, site, sym, env, resultInfo) :
checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo);
}
Type checkMethodId(JCTree tree,
Type site,
Symbol sym,
Env<AttrContext> env,
ResultInfo resultInfo) {
boolean isPolymorhicSignature =
(sym.baseSymbol().flags() & SIGNATURE_POLYMORPHIC) != 0;
return isPolymorhicSignature ?
checkSigPolyMethodId(tree, site, sym, env, resultInfo) :
checkMethodIdInternal(tree, site, sym, env, resultInfo);
}
Type checkSigPolyMethodId(JCTree tree,
Type site,
Symbol sym,
Env<AttrContext> env,
ResultInfo resultInfo) {
//recover original symbol for signature polymorphic methods
checkMethodIdInternal(tree, site, sym.baseSymbol(), env, resultInfo);
env.info.pendingResolutionPhase = Resolve.MethodResolutionPhase.BASIC;
return sym.type;
}
Type checkMethodIdInternal(JCTree tree,
Type site,
Symbol sym,

View File

@ -90,6 +90,7 @@ public class Check {
private final JCDiagnostic.Factory diags;
private final JavaFileManager fileManager;
private final Source source;
private final Target target;
private final Profile profile;
private final boolean warnOnAnyAccessToMembers;
@ -130,6 +131,7 @@ public class Check {
fileManager = context.get(JavaFileManager.class);
source = Source.instance(context);
target = Target.instance(context);
warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
Target target = Target.instance(context);
@ -1001,9 +1003,10 @@ public class Check {
!isTrustMeAllowedOnMethod(sym))) {
warnUnchecked(env.tree.pos(), Warnings.UncheckedGenericArrayCreation(argtype));
}
if ((sym.baseSymbol().flags() & SIGNATURE_POLYMORPHIC) == 0) {
TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
}
TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
}
if ((sym.flags() & SIGNATURE_POLYMORPHIC) != 0 && !target.hasMethodHandles()) {
log.error(env.tree, Errors.BadTargetSigpolyCall(target, Target.JDK1_7));
}
return owntype;
}

View File

@ -883,8 +883,9 @@ public class DeferredAttr extends JCTree.Visitor {
Check.CheckContext checkContext = resultInfo.checkContext;
Type pt = resultInfo.pt;
if (!inferenceContext.inferencevars.contains(pt)) {
Type descriptor = null;
try {
types.findDescriptorType(pt);
descriptor = types.findDescriptorType(pt);
} catch (Types.FunctionDescriptorLookupError ex) {
checkContext.report(null, ex.getDiagnostic());
}
@ -893,14 +894,14 @@ public class DeferredAttr extends JCTree.Visitor {
exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
attr.memberReferenceQualifierResult(tree), argumentAttr.withLocalCacheContext());
ListBuffer<Type> argtypes = new ListBuffer<>();
for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
for (Type t : descriptor.getParameterTypes()) {
argtypes.append(Type.noType);
}
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
mref2.expr = exprTree;
Symbol lookupSym =
rs.resolveMemberReference(localEnv, mref2, exprTree.type,
tree.name, argtypes.toList(), List.nil(), rs.arityMethodCheck,
tree.name, argtypes.toList(), List.nil(), descriptor, rs.arityMethodCheck,
inferenceContext, rs.structuralReferenceChooser).fst;
switch (lookupSym.kind) {
case WRONG_MTH:

View File

@ -485,9 +485,7 @@ public class LambdaToMethod extends TreeTranslator {
//first determine the method symbol to be used to generate the sam instance
//this is either the method reference symbol, or the bridged reference symbol
Symbol refSym = localContext.isSignaturePolymorphic()
? localContext.sigPolySym
: tree.sym;
Symbol refSym = tree.sym;
//the qualifying expression is treated as a special captured arg
JCExpression init;
@ -2309,17 +2307,10 @@ public class LambdaToMethod extends TreeTranslator {
final class ReferenceTranslationContext extends TranslationContext<JCMemberReference> {
final boolean isSuper;
final Symbol sigPolySym;
ReferenceTranslationContext(JCMemberReference tree) {
super(tree);
this.isSuper = tree.hasKind(ReferenceKind.SUPER);
this.sigPolySym = isSignaturePolymorphic()
? makePrivateSyntheticMethod(tree.sym.flags(),
tree.sym.name,
bridgedRefSig(),
tree.sym.enclClass())
: null;
}
/**
@ -2364,15 +2355,6 @@ public class LambdaToMethod extends TreeTranslator {
!owner.enclClass().isSubClass(tree.sym.owner, types));
}
/**
* Signature polymorphic methods need special handling.
* e.g. MethodHandle.invoke() MethodHandle.invokeExact()
*/
final boolean isSignaturePolymorphic() {
return tree.sym.kind == MTH &&
types.isSignaturePolymorphic((MethodSymbol)tree.sym);
}
/**
* Erasure destroys the implementation parameter subtype
* relationship for intersection types.

View File

@ -2648,6 +2648,7 @@ public class Resolve {
} else if (allowMethodHandles) {
MethodSymbol msym = (MethodSymbol)sym;
if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) {
env.info.pendingResolutionPhase = BASIC;
return findPolymorphicSignatureInstance(env, sym, argtypes);
}
}
@ -2668,6 +2669,11 @@ public class Resolve {
List<Type> argtypes) {
Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
(MethodSymbol)spMethod, currentResolutionContext, argtypes);
return findPolymorphicSignatureInstance(spMethod, mtype);
}
Symbol findPolymorphicSignatureInstance(final Symbol spMethod,
Type mtype) {
for (Symbol sym : polymorphicSignatureScope.getSymbolsByName(spMethod.name)) {
// Check that there is already a method symbol for the method
// type and owner
@ -2935,6 +2941,7 @@ public class Resolve {
Name name,
List<Type> argtypes,
List<Type> typeargtypes,
Type descriptor,
MethodCheck methodCheck,
InferenceContext inferenceContext,
ReferenceChooser referenceChooser) {
@ -2972,6 +2979,15 @@ public class Resolve {
unboundEnv.info.pendingResolutionPhase :
boundEnv.info.pendingResolutionPhase;
if (!res.fst.kind.isResolutionError()) {
//handle sigpoly method references
MethodSymbol msym = (MethodSymbol)res.fst;
if ((msym.flags() & SIGNATURE_POLYMORPHIC) != 0) {
env.info.pendingResolutionPhase = BASIC;
res = new Pair<>(findPolymorphicSignatureInstance(msym, descriptor), res.snd);
}
}
return res;
}

View File

@ -92,7 +92,6 @@ public class TransTypes extends TreeTranslator {
log = Log.instance(context);
syms = Symtab.instance(context);
enter = Enter.instance(context);
bridgeSpans = new HashMap<>();
types = Types.instance(context);
make = TreeMaker.instance(context);
resolve = Resolve.instance(context);
@ -103,13 +102,6 @@ public class TransTypes extends TreeTranslator {
attr = Attr.instance(context);
}
/** A hashtable mapping bridge methods to the pair of methods they bridge.
* The bridge overrides the first of the pair after type erasure and deflects
* to the second of the pair (which differs in type erasure from the one
* it overrides thereby necessitating the bridge)
*/
Map<MethodSymbol, Pair<MethodSymbol, MethodSymbol>> bridgeSpans;
/** Construct an attributed tree for a cast of expression to target type,
* unless it already has precisely that type.
* @param tree The expression tree.
@ -243,17 +235,12 @@ public class TransTypes extends TreeTranslator {
* @param meth The method for which a bridge needs to be added
* @param impl That method's implementation (possibly the method itself)
* @param origin The class to which the bridge will be added
* @param hypothetical
* True if the bridge method is not strictly necessary in the
* binary, but is represented in the symbol table to detect
* erasure clashes.
* @param bridges The list buffer to which the bridge will be added
*/
void addBridge(DiagnosticPosition pos,
MethodSymbol meth,
MethodSymbol impl,
ClassSymbol origin,
boolean hypothetical,
ListBuffer<JCTree> bridges) {
make.at(pos);
Type implTypeErasure = erasure(impl.type);
@ -262,7 +249,6 @@ public class TransTypes extends TreeTranslator {
Type bridgeType = meth.erasure(types);
long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE |
(origin.isInterface() ? DEFAULT : 0);
if (hypothetical) flags |= HYPOTHETICAL;
MethodSymbol bridge = new MethodSymbol(flags,
meth.name,
bridgeType,
@ -273,38 +259,35 @@ public class TransTypes extends TreeTranslator {
bridge.params = createBridgeParams(impl, bridge, bridgeType);
bridge.setAttributes(impl);
if (!hypothetical) {
JCMethodDecl md = make.MethodDef(bridge, null);
JCMethodDecl md = make.MethodDef(bridge, null);
// The bridge calls this.impl(..), if we have an implementation
// in the current class, super.impl(...) otherwise.
JCExpression receiver = (impl.owner == origin)
? make.This(origin.erasure(types))
: make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
// The bridge calls this.impl(..), if we have an implementation
// in the current class, super.impl(...) otherwise.
JCExpression receiver = (impl.owner == origin)
? make.This(origin.erasure(types))
: make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
// The type returned from the original method.
Type calltype = implTypeErasure.getReturnType();
// The type returned from the original method.
Type calltype = implTypeErasure.getReturnType();
// Construct a call of this.impl(params), or super.impl(params),
// casting params and possibly results as needed.
JCExpression call =
make.Apply(
null,
make.Select(receiver, impl).setType(calltype),
translateArgs(make.Idents(md.params), implTypeErasure.getParameterTypes(), null))
.setType(calltype);
JCStatement stat = (implTypeErasure.getReturnType().hasTag(VOID))
? make.Exec(call)
: make.Return(coerce(call, bridgeType.getReturnType()));
md.body = make.Block(0, List.of(stat));
// Construct a call of this.impl(params), or super.impl(params),
// casting params and possibly results as needed.
JCExpression call =
make.Apply(
null,
make.Select(receiver, impl).setType(calltype),
translateArgs(make.Idents(md.params), implTypeErasure.getParameterTypes(), null))
.setType(calltype);
JCStatement stat = (implTypeErasure.getReturnType().hasTag(VOID))
? make.Exec(call)
: make.Return(coerce(call, bridgeType.getReturnType()));
md.body = make.Block(0, List.of(stat));
// Add bridge to `bridges' buffer
bridges.append(md);
}
// Add bridge to `bridges' buffer
bridges.append(md);
// Add bridge to scope of enclosing class and keep track of the bridge span.
origin.members().enter(bridge);
bridgeSpans.put(bridge, new Pair<>(meth, impl));
}
private List<VarSymbol> createBridgeParams(MethodSymbol impl, MethodSymbol bridge,
@ -350,11 +333,10 @@ public class TransTypes extends TreeTranslator {
ClassSymbol origin,
ListBuffer<JCTree> bridges) {
if (sym.kind == MTH &&
sym.name != names.init &&
(sym.flags() & (PRIVATE | STATIC)) == 0 &&
(sym.flags() & SYNTHETIC) != SYNTHETIC &&
sym.isMemberOf(origin, types))
{
sym.name != names.init &&
(sym.flags() & (PRIVATE | STATIC)) == 0 &&
(sym.flags() & SYNTHETIC) != SYNTHETIC &&
sym.isMemberOf(origin, types)) {
MethodSymbol meth = (MethodSymbol)sym;
MethodSymbol bridge = meth.binaryImplementation(origin, types);
MethodSymbol impl = meth.implementation(origin, types, true);
@ -362,8 +344,8 @@ public class TransTypes extends TreeTranslator {
bridge == meth ||
(impl != null && !bridge.owner.isSubClass(impl.owner, types))) {
// No bridge was added yet.
if (impl != null && isBridgeNeeded(meth, impl, origin.type)) {
addBridge(pos, meth, impl, origin, bridge==impl, bridges);
if (impl != null && bridge != impl && isBridgeNeeded(meth, impl, origin.type)) {
addBridge(pos, meth, impl, origin, bridges);
} else if (impl == meth
&& impl.owner != origin
&& (impl.flags() & FINAL) == 0
@ -371,36 +353,7 @@ public class TransTypes extends TreeTranslator {
&& (origin.flags() & PUBLIC) > (impl.owner.flags() & PUBLIC)) {
// this is to work around a horrible but permanent
// reflection design error.
addBridge(pos, meth, impl, origin, false, bridges);
}
} else if ((bridge.flags() & SYNTHETIC) == SYNTHETIC) {
final Pair<MethodSymbol, MethodSymbol> bridgeSpan = bridgeSpans.get(bridge);
MethodSymbol other = bridgeSpan == null ? null : bridgeSpan.fst;
if (other != null && other != meth) {
if (impl == null || !impl.overrides(other, origin, types, true)) {
// Is bridge effectively also the bridge for `meth', if so no clash.
MethodSymbol target = bridgeSpan == null ? null : bridgeSpan.snd;
if (target == null || !target.overrides(meth, origin, types, true, false)) {
// Bridge for other symbol pair was added
log.error(pos, Errors.NameClashSameErasureNoOverride(
other.name, types.memberType(origin.type, other).asMethodType().getParameterTypes(),
other.location(origin.type, types),
meth.name, types.memberType(origin.type, meth).asMethodType().getParameterTypes(),
meth.location(origin.type, types)));
}
}
}
} else if (!bridge.overrides(meth, origin, types, true)) {
// Accidental binary override without source override.
// Don't diagnose the problem if it would already
// have been reported in the superclass
if (bridge.owner == origin ||
types.asSuper(bridge.owner.type, meth.owner) == null) {
log.error(pos, Errors.NameClashSameErasureNoOverride(
bridge.name, types.memberType(origin.type, bridge).asMethodType().getParameterTypes(),
bridge.location(origin.type, types),
meth.name, types.memberType(origin.type, meth).asMethodType().getParameterTypes(),
meth.location(origin.type, types)));
addBridge(pos, meth, impl, origin, bridges);
}
}
}
@ -539,16 +492,6 @@ public class TransTypes extends TreeTranslator {
} finally {
currentMethod = previousMethod;
}
// Check that we do not introduce a name clash by erasing types.
for (Symbol sym : tree.sym.owner.members().getSymbolsByName(tree.name)) {
if (sym != tree.sym &&
types.isSameType(erasure(sym.type), tree.type)) {
log.error(tree.pos(),
Errors.NameClashSameErasure(tree.sym, sym));
return;
}
}
}
public void visitVarDef(JCVariableDecl tree) {
@ -689,9 +632,8 @@ public class TransTypes extends TreeTranslator {
tree.varargsElement = types.erasure(tree.varargsElement);
else
if (tree.args.length() != argtypes.length()) {
log.error(tree.pos(),
Errors.MethodInvokedWithIncorrectNumberArguments(tree.args.length(),
argtypes.length()));
Assert.error(String.format("Incorrect number of arguments; expected %d, found %d",
tree.args.length(), argtypes.length()));
}
tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);

View File

@ -1098,10 +1098,6 @@ compiler.err.signature.doesnt.match.supertype=\
compiler.err.signature.doesnt.match.intf=\
signature does not match {0}; incompatible interfaces
# 0: number, 1: number
compiler.err.method.invoked.with.incorrect.number.arguments=\
method invoked with incorrect number of arguments; expected {0}, found {1}
# 0: symbol, 1: symbol, 2: symbol
compiler.err.does.not.override.abstract=\
{0} is not abstract and does not override abstract method {1} in {2}
@ -1723,6 +1719,11 @@ compiler.warn.inexact.non-varargs.call=\
cast to {0} for a varargs call\n\
cast to {1} for a non-varargs call and to suppress this warning
# 0: target, 1: target
compiler.err.bad.target.sigpoly.call=\
polymorphic signature calls are not supported in -target {0}\n\
(use -target {1} or higher to enable polymorphic signature calls)
# 0: list of type
compiler.warn.unreachable.catch=\
unreachable catch clause\n\

View File

@ -0,0 +1,15 @@
/*
* @test /nodynamiccopyright/
* @bug 8013179
* @summary assertion failure in javac when compiling with -source 1.6 -target 1.6
* @compile/fail/ref=T8013179.out -source 6 -target 6 -Xlint:-options -XDrawDiagnostics T8013179.java
*/
import java.lang.invoke.MethodHandle;
class T8013179 {
static MethodHandle getNamedMember;
public static Object getMember(String name, Object rec) throws Throwable {
return getNamedMember.invoke(rec, name);
}
}

View File

@ -0,0 +1,2 @@
T8013179.java:13:37: compiler.err.bad.target.sigpoly.call: 1.6, 1.7
1 error

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2018, 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 8133247
* @summary Use of HYPOTHETICAL flag in bridge generation logic leads to missing bridges in some cases
*/
import java.lang.reflect.Method;
public class T8133247 {
public static void main(String[] args) throws Exception {
Method m = Class.forName("p.B").getMethod("f", Object.class);
m.invoke(new p.B(), new Object[]{null});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018, 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 p;
class A<T> implements I<T> {
public void f(T t) {}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2018, 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 p;
public class B extends A<String> {}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018, 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 p;
public interface I<T> {
void f(T t);
}

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.method.invoked.with.incorrect.number.arguments
// key: compiler.err.bad.target.sigpoly.call
// options: -Xlint:-options -source 6 -target 6
class MethodInvokedWithWrongNumberOfArgs {