Skip to content

Commit 08abcb2

Browse files
committed
[GR-5496] Fix method overload selection with covariant return type overrides and bridge methods.
PullRequest: graal/405
2 parents 4bdeeb2 + f80e48c commit 08abcb2

File tree

2 files changed

+38
-21
lines changed
  • truffle/src
    • com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test
    • com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java

2 files changed

+38
-21
lines changed

truffle/src/com.oracle.truffle.api.interop.java.test/src/com/oracle/truffle/api/interop/java/test/OverloadedTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,30 @@ public void testOverloadingNumber() throws InteropException {
138138
assertEquals("BigInteger", num.parameter);
139139
}
140140

141+
public interface Identity<T> {
142+
T getId();
143+
}
144+
145+
public interface SomeThingWithIdentity extends Identity<Integer> {
146+
@Override
147+
Integer getId();
148+
}
149+
150+
public static class ActualRealThingWithIdentity implements SomeThingWithIdentity {
151+
Integer id = 42;
152+
153+
@Override
154+
public Integer getId() {
155+
return id;
156+
}
157+
}
158+
159+
@Test
160+
public void testGenericReturnTypeBridgeMethod() throws InteropException {
161+
TruffleObject thing = JavaInterop.asTruffleObject(new ActualRealThingWithIdentity());
162+
assertEquals(42, ForeignAccess.sendInvoke(Message.createInvoke(0).createNode(), thing, "getId"));
163+
}
164+
141165
@MessageResolution(receiverType = UnboxableToInt.class)
142166
public static final class UnboxableToInt implements TruffleObject {
143167

truffle/src/com.oracle.truffle.api.interop.java/src/com/oracle/truffle/api/interop/java/JavaClassDesc.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,9 @@ public JavaMethodDesc apply(JavaMethodDesc m1, JavaMethodDesc m2) {
8989
JavaMethodDesc ctor = null;
9090
JavaMethodDesc functionalInterfaceMethod = null;
9191

92-
if (Modifier.isPublic(type.getModifiers())) {
93-
for (Method m : type.getMethods()) {
94-
if (!Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
95-
/*
96-
* If a method is declared in a non-public direct superclass, there should
97-
* be a public bridge method in this class that provides access to it.
98-
*
99-
* In some more elaborate class hierarchies, or if the method is declared in
100-
* an interface (i.e. a default method), no bridge method is generated, so
101-
* search the whole inheritance hierarchy for accessible methods.
102-
*/
103-
methodMap.clear();
104-
staticMethodMap.clear();
105-
collectPublicMethods(type, methodMap, staticMethodMap);
106-
break;
107-
}
108-
putMethod(m, methodMap, staticMethodMap);
109-
}
92+
collectPublicMethods(type, methodMap, staticMethodMap);
11093

94+
if (Modifier.isPublic(type.getModifiers())) {
11195
boolean inheritedPublicInstanceFields = false;
11296
boolean inheritedPublicInaccessibleFields = false;
11397
for (Field f : type.getFields()) {
@@ -133,9 +117,6 @@ public JavaMethodDesc apply(JavaMethodDesc m1, JavaMethodDesc m2) {
133117
collectPublicInstanceFields(type, fieldMap, inheritedPublicInaccessibleFields);
134118
}
135119
} else {
136-
// If the class is not public, look for inherited public methods.
137-
collectPublicMethods(type, methodMap, staticMethodMap);
138-
139120
if (!Modifier.isInterface(type.getModifiers())) {
140121
collectPublicInstanceFields(type, fieldMap, true);
141122
}
@@ -177,6 +158,14 @@ private static void collectPublicMethods(Class<?> type, Map<String, JavaMethodDe
177158
if (isPublicType) {
178159
for (Method m : type.getMethods()) {
179160
if (!Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
161+
/*
162+
* If a method is declared in a non-public direct superclass, there should
163+
* be a public bridge method in this class that provides access to it.
164+
*
165+
* In some more elaborate class hierarchies, or if the method is declared in
166+
* an interface (i.e. a default method), no bridge method is generated, so
167+
* search the whole inheritance hierarchy for accessible methods.
168+
*/
180169
allMethodsPublic = false;
181170
continue;
182171
} else if (Modifier.isStatic(m.getModifiers()) && (m.getDeclaringClass() != startType && Modifier.isInterface(m.getDeclaringClass().getModifiers()))) {
@@ -189,6 +178,10 @@ private static void collectPublicMethods(Class<?> type, Map<String, JavaMethodDe
189178
}
190179
}
191180
}
181+
/*
182+
* Look for inherited public methods if the class/interface is not public or if we have
183+
* seen a public method declared in a non-public class (see above).
184+
*/
192185
if (!isPublicType || !allMethodsPublic) {
193186
if (type.getSuperclass() != null) {
194187
collectPublicMethods(type.getSuperclass(), methodMap, staticMethodMap, visited, startType);

0 commit comments

Comments
 (0)