Lines 68-98
Link Here
|
68 |
// 15.12.2.8 - inferring unresolved type arguments |
68 |
// 15.12.2.8 - inferring unresolved type arguments |
69 |
if (hasUnresolvedTypeArgument(substitutes)) { |
69 |
if (hasUnresolvedTypeArgument(substitutes)) { |
70 |
TypeBinding expectedType = null; |
70 |
TypeBinding expectedType = null; |
71 |
// if message invocation has expected type |
71 |
if (methodSubstitute.returnType != VoidBinding) { |
72 |
if (invocationSite instanceof MessageSend) { |
72 |
// if message invocation has expected type |
73 |
MessageSend message = (MessageSend) invocationSite; |
73 |
if (invocationSite instanceof MessageSend) { |
74 |
expectedType = message.expectedType; |
74 |
MessageSend message = (MessageSend) invocationSite; |
75 |
} |
75 |
expectedType = message.expectedType; |
76 |
TypeBinding upperBound; |
76 |
} |
77 |
TypeBinding substitutedReturnType = methodSubstitute.returnType; |
77 |
if (expectedType == null) expectedType = scope.getJavaLangObject(); // assume Object by default |
78 |
switch (substitutedReturnType.kind()) { |
|
|
79 |
case Binding.TYPE_PARAMETER : |
80 |
// should be: if no expected type, then assume Object |
81 |
// actually it rather seems to handle the returned variable case by expecting its erasure instead |
82 |
upperBound = Scope.substitute(methodSubstitute, ((TypeVariableBinding)substitutedReturnType).upperBound()); |
83 |
break; |
84 |
case Binding.BASE_TYPE : |
85 |
if (substitutedReturnType == VoidBinding) { |
86 |
upperBound = null; |
87 |
break; |
88 |
} |
89 |
// fallthrough |
90 |
default: |
91 |
upperBound = scope.getJavaLangObject(); |
92 |
} |
93 |
// Object o = foo(); // where <T extends Serializable> T foo(); |
94 |
if (expectedType == null || (upperBound != null && upperBound.isCompatibleWith(expectedType))) { |
95 |
expectedType = upperBound; |
96 |
} |
78 |
} |
97 |
methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, collectedSubstitutes, substitutes); |
79 |
methodSubstitute = methodSubstitute.inferFromExpectedType(scope, expectedType, collectedSubstitutes, substitutes); |
98 |
if (methodSubstitute == null) |
80 |
if (methodSubstitute == null) |
Lines 208-213
Link Here
|
208 |
for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) { |
190 |
for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) { |
209 |
TypeBinding equalSubstitute = equalSubstitutes[j]; |
191 |
TypeBinding equalSubstitute = equalSubstitutes[j]; |
210 |
if (equalSubstitute == null) continue nextConstraint; |
192 |
if (equalSubstitute == null) continue nextConstraint; |
|
|
193 |
// if (equalSubstitute == current) continue nextConstraint; |
211 |
if (equalSubstitute == current) { |
194 |
if (equalSubstitute == current) { |
212 |
// try to find a better different match if any in subsequent equal candidates |
195 |
// try to find a better different match if any in subsequent equal candidates |
213 |
for (int k = j+1; k < equalLength; k++) { |
196 |
for (int k = j+1; k < equalLength; k++) { |
Lines 387-405
Link Here
|
387 |
computeSubstitutes: { |
370 |
computeSubstitutes: { |
388 |
// infer from expected return type |
371 |
// infer from expected return type |
389 |
if (expectedType != null) { |
372 |
if (expectedType != null) { |
390 |
returnType.collectSubstitutes(scope, expectedType, collectedSubstitutes, CONSTRAINT_SUPER); |
373 |
this.returnType.collectSubstitutes(scope, expectedType, collectedSubstitutes, CONSTRAINT_SUPER); |
391 |
} |
374 |
} |
392 |
// infer from bounds of type parameters |
375 |
// infer from bounds of type parameters |
393 |
for (int i = 0; i < varLength; i++) { |
376 |
for (int i = 0; i < varLength; i++) { |
394 |
TypeVariableBinding originalVariable = originalVariables[i]; |
377 |
TypeVariableBinding originalVariable = originalVariables[i]; |
395 |
TypeBinding argument = this.typeArguments[i]; |
378 |
TypeBinding argument = this.typeArguments[i]; |
|
|
379 |
boolean argAlreadyInferred = argument != originalVariable; |
396 |
if (originalVariable.firstBound == originalVariable.superclass) { |
380 |
if (originalVariable.firstBound == originalVariable.superclass) { |
397 |
Scope.substitute(this, originalVariable.firstBound) // substitue original bound with resolved variables |
381 |
TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass); |
398 |
.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); |
382 |
argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER); |
|
|
383 |
// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference |
384 |
// e.g. given: <E extends Object, S extends Collection<E>> S test1(S param) |
385 |
// invocation: test1(new Vector<String>()) will infer: S=Vector<String> and with code below: E=String |
386 |
if (argAlreadyInferred) |
387 |
substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); |
399 |
} |
388 |
} |
400 |
for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) { |
389 |
for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) { |
401 |
Scope.substitute(this, originalVariable.superInterfaces[j]) // substitue original bound with resolved variables |
390 |
TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]); |
402 |
.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); |
391 |
argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER); |
|
|
392 |
// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference |
393 |
if (argAlreadyInferred) |
394 |
substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS); |
403 |
} |
395 |
} |
404 |
} |
396 |
} |
405 |
substitutes = resolveSubstituteConstraints(scope, originalVariables, substitutes, true/*consider Ti<:Uk*/, collectedSubstitutes); |
397 |
substitutes = resolveSubstituteConstraints(scope, originalVariables, substitutes, true/*consider Ti<:Uk*/, collectedSubstitutes); |