one more case of KT-445 Don't allow deep instanceof for erased parameters

===
(a : List<out Any>) is List<out Int>
===
This commit is contained in:
Stepan Koltsov
2011-12-01 17:41:13 +04:00
parent a003e6d2e4
commit 52c1e9a950
4 changed files with 56 additions and 27 deletions
@@ -248,7 +248,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (typeChecker.isSubtypeOf(actualType, targetType)) { if (typeChecker.isSubtypeOf(actualType, targetType)) {
context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign())); context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign()));
} else { } else {
if (isCastErased(actualType, targetType)) { if (isCastErased(actualType, targetType, typeChecker)) {
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType)); context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
} }
} }
@@ -259,13 +259,36 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
* Check if assignment from ActualType to TargetType is erased. * Check if assignment from ActualType to TargetType is erased.
* It is an error in "is" statement and warning in "as". * It is an error in "is" statement and warning in "as".
*/ */
public static boolean isCastErased(JetType actualType, JetType targetType) { public static boolean isCastErased(JetType actualType, JetType targetType, JetTypeChecker typeChecker) {
if (!(targetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { if (!(targetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
// TODO: what if it is TypeParameterDescriptor? // TODO: what if it is TypeParameterDescriptor?
return false; return false;
} }
{
Multimap<TypeConstructor, TypeProjection> typeSubstitutionMap =
TypeUtils.buildDeepSubstitutionMultimap(targetType);
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
TypeProjection actualTypeParameter = actualType.getArguments().get(i);
TypeParameterDescriptor subjectTypeParameterDescriptor = actualType.getConstructor().getParameters().get(i);
if (subjectTypeParameterDescriptor.isReified()) {
continue;
}
Collection<TypeProjection> subst = typeSubstitutionMap.get(subjectTypeParameterDescriptor.getTypeConstructor());
for (TypeProjection proj : subst) {
//if (!proj.getType().equals(actualTypeParameter.getType())) {
if (!typeChecker.isSubtypeOf(actualTypeParameter.getType(), proj.getType())) {
return true;
}
}
}
}
{
JetType targetTypeClerared = TypeUtils.makeUnsubstitutedType( JetType targetTypeClerared = TypeUtils.makeUnsubstitutedType(
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null); (ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
@@ -301,6 +324,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return true; return true;
} }
} }
}
return false; return false;
} }
@@ -246,7 +246,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
return; return;
} }
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type)) { if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, context.semanticServices.getTypeChecker())) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(reportErrorOn, type)); context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(reportErrorOn, type));
} }
} }
@@ -0,0 +1,5 @@
// +JDK
import java.util.List
fun f(a : List<out Any>) = a is <!CANNOT_CHECK_FOR_ERASED!>List<out Int><!>
@@ -4,5 +4,5 @@
class IdUnavailableException() : Exception() {} class IdUnavailableException() : Exception() {}
fun <T : Any> T.getJavaClass() : Class<T> { fun <T : Any> T.getJavaClass() : Class<T> {
return ((this <!CAST_NEVER_SUCCEEDS!>as<!> Object).getClass()) as Class<T> // Some error here, because of Exception() used above. ?!!! return <!UNCHECKED_CAST!>((this <!CAST_NEVER_SUCCEEDS!>as<!> Object).getClass()) as Class<T><!> // Some error here, because of Exception() used above. ?!!!
} }