return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression);
default :
if (castType.isInterface()) {
// ( INTERFACE ) INTERFACE
ReferenceBinding interfaceType = (ReferenceBinding) expressionType;
match = interfaceType.findSuperTypeOriginatingFrom(castType);
if (match != null) {
return checkUnsafeCast(scope, castType, interfaceType, match, false);
}
tagAsNeedCheckCast();
match = castType.findSuperTypeOriginatingFrom(interfaceType);
if (match != null) {
return checkUnsafeCast(scope, castType, interfaceType, match, true);
}
if (use15specifics) {
checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true);
// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) {
if (interfaceType.hasIncompatibleSuperType((ReferenceBinding) castType)) {
return false;
}
} else if (!castType.isRawType() && interfaceType.hasIncompatibleSuperType((ReferenceBinding) castType)) {
return false;
}
} else {
// pre1.5 semantics - no covariance allowed (even if 1.5 compliant, but 1.4 source)
// look at original methods rather than the parameterized variants at 1.4 to detect
// covariance. Otherwise when confronted with one raw type and one parameterized type,
// we could mistakenly detect covariance and scream foul. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=332744
MethodBinding[] castTypeMethods = getAllOriginalInheritedMethods((ReferenceBinding) castType);
MethodBinding[] expressionTypeMethods = getAllOriginalInheritedMethods((ReferenceBinding) expressionType);
int exprMethodsLength = expressionTypeMethods.length;
for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++) {
for (int j = 0; j < exprMethodsLength; j++) {
if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
&& (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
return false;
}
}
}
}
return true;
} else {
// ( CLASS ) INTERFACE
if (castType.id == TypeIds.T_JavaLangObject) { // no runtime error
tagAsUnnecessaryCast(scope, castType);
return true;
}
// can only be a downcast
tagAsNeedCheckCast();
match = castType.findSuperTypeOriginatingFrom(expressionType);
if (match != null) {
return checkUnsafeCast(scope, castType, expressionType, match, true);
}
if (((ReferenceBinding) castType).isFinal()) {
// no subclass for castType, thus compile-time check is invalid
return false;
}
if (use15specifics) {
checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true);
// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) {
if (((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBinding) expressionType)) {
return false;
}
} else if (!castType.isRawType() && ((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBinding) expressionType)) {
return false;
}
}
return true;
}
}
} else {
switch (castType.kind()) {
case Binding.ARRAY_TYPE :
// ( ARRAY ) CLASS
if (expressionType.id == TypeIds.T_JavaLangObject) { // potential runtime error
if (use15specifics) checkUnsafeCast(scope, castType, expressionType, expressionType, true);
tagAsNeedCheckCast();
return true;
}
return false;
case Binding.TYPE_PARAMETER :
// ( TYPE_PARAMETER ) CLASS
match = expressionType.findSuperTypeOriginatingFrom(castType);
if (match == null) {
checkUnsafeCast(scope, castType, expressionType, null, true);
}
// recurse on the type variable upper bound
return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionType, expression);
default :
if (castType.isInterface()) {
// ( INTERFACE ) CLASS
ReferenceBinding refExprType = (ReferenceBinding) expressionType;
match = refExprType.findSuperTypeOriginatingFrom(castType);
if (match != null) {
return checkUnsafeCast(scope, castType, expressionType, match, false);
}
// unless final a subclass may implement the interface ==> no check at compile time
if (refExprType.isFinal()) {
return false;
}
tagAsNeedCheckCast();
match = castType.findSuperTypeOriginatingFrom(expressionType);
if (match != null) {
return checkUnsafeCast(scope, castType, expressionType, match, true);
}
if (use15specifics) {
checkUnsafeCast(scope, castType, expressionType, null /*no match*/, true);
// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
if (scope.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) {
if (refExprType.hasIncompatibleSuperType((ReferenceBinding) castType)) {
return false;
}
} else if (!castType.isRawType() && refExprType.hasIncompatibleSuperType((ReferenceBinding) castType)) {
return false;
}
}
return true;
} else {