private static boolean resolveSubstituteConstraints( Scope scope, TypeVariableBinding[] typeVariables, InferenceContext inferenceContext, boolean considerEXTENDSConstraints) { TypeBinding[] substitutes = inferenceContext.substitutes; int varLength = typeVariables.length; // check Tj=U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] equalSubstitutes = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EQUAL); if (equalSubstitutes != null) { nextConstraint: for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) { TypeBinding equalSubstitute = equalSubstitutes[j]; if (equalSubstitute == null) continue nextConstraint; if (equalSubstitute == current) { // try to find a better different match if any in subsequent equal candidates for (int k = j + 1; k < equalLength; k++) { equalSubstitute = equalSubstitutes[k]; if (equalSubstitute != current && equalSubstitute != null) { substitutes[i] = equalSubstitute; continue nextTypeParameter; } } substitutes[i] = current; continue nextTypeParameter; } // if (equalSubstitute.isTypeVariable()) { // TypeVariableBinding variable = (TypeVariableBinding) equalSubstitute; // // substituted by a variable of the same method, ignore // if (variable.rank < varLength && typeVariables[variable.rank] == variable) { // // TODO (philippe) rewrite all other constraints to use current instead. // continue nextConstraint; // } // } substitutes[i] = equalSubstitute; continue nextTypeParameter; // pick first match, applicability check will rule out invalid // scenario where others were present } } } if (inferenceContext.hasUnresolvedTypeArgument()) { // check Tj>:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_SUPER); if (bounds == null) continue nextTypeParameter; TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds); if (mostSpecificSubstitute == null) { return false; // incompatible } if (mostSpecificSubstitute != TypeBinding.VOID) { substitutes[i] = mostSpecificSubstitute; } } } if (considerEXTENDSConstraints && inferenceContext.hasUnresolvedTypeArgument()) { // check Tj<:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS); if (bounds == null) continue nextTypeParameter; TypeBinding[] glb = Scope.greaterLowerBound(bounds); TypeBinding mostSpecificSubstitute = null; if (glb != null) mostSpecificSubstitute = glb[0]; // TODO (philippe) need to improve // TypeBinding mostSpecificSubstitute = scope.greaterLowerBound(bounds); if (mostSpecificSubstitute != null) { substitutes[i] = mostSpecificSubstitute; } } } return true; }
private static boolean resolveSubstituteConstraints( Scope scope, TypeVariableBinding[] typeVariables, InferenceContext inferenceContext, boolean considerEXTENDSConstraints) { TypeBinding[] substitutes = inferenceContext.substitutes; int varLength = typeVariables.length; // check Tj=U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] equalSubstitutes = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EQUAL); if (equalSubstitutes != null) { nextConstraint: for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) { TypeBinding equalSubstitute = equalSubstitutes[j]; if (equalSubstitute == null) continue nextConstraint; if (equalSubstitute == current) { // try to find a better different match if any in subsequent equal candidates for (int k = j + 1; k < equalLength; k++) { equalSubstitute = equalSubstitutes[k]; if (equalSubstitute != current && equalSubstitute != null) { substitutes[i] = equalSubstitute; continue nextTypeParameter; } } substitutes[i] = current; continue nextTypeParameter; } // if (equalSubstitute.isTypeVariable()) { // TypeVariableBinding variable = (TypeVariableBinding) equalSubstitute; // // substituted by a variable of the same method, ignore // if (variable.rank < varLength && typeVariables[variable.rank] == variable) { // // TODO (philippe) rewrite all other constraints to use current instead. // continue nextConstraint; // } // } substitutes[i] = equalSubstitute; continue nextTypeParameter; // pick first match, applicability check will rule out invalid // scenario where others were present } } } if (inferenceContext.hasUnresolvedTypeArgument()) { // check Tj>:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_SUPER); if (bounds == null) continue nextTypeParameter; TypeBinding mostSpecificSubstitute = scope.lowerUpperBound(bounds); if (mostSpecificSubstitute == null) { return false; // incompatible } if (mostSpecificSubstitute != TypeBinding.VOID) { substitutes[i] = mostSpecificSubstitute; } } } if (considerEXTENDSConstraints && inferenceContext.hasUnresolvedTypeArgument()) { // check Tj<:U constraints nextTypeParameter: for (int i = 0; i < varLength; i++) { TypeVariableBinding current = typeVariables[i]; TypeBinding substitute = substitutes[i]; if (substitute != null) continue nextTypeParameter; // already inferred previously TypeBinding[] bounds = inferenceContext.getSubstitutes(current, TypeConstants.CONSTRAINT_EXTENDS); if (bounds == null) continue nextTypeParameter; TypeBinding[] glb = Scope.greaterLowerBound(bounds, scope, scope.environment()); TypeBinding mostSpecificSubstitute = null; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=341795 - Per 15.12.2.8, we should fully // apply glb if (glb != null) { if (glb.length == 1) { mostSpecificSubstitute = glb[0]; } else { TypeBinding[] otherBounds = new TypeBinding[glb.length - 1]; System.arraycopy(glb, 1, otherBounds, 0, glb.length - 1); mostSpecificSubstitute = scope.environment().createWildcard(null, 0, glb[0], otherBounds, Wildcard.EXTENDS); } } if (mostSpecificSubstitute != null) { substitutes[i] = mostSpecificSubstitute; } } } return true; }