Erased casts supported

This commit is contained in:
Andrey Breslav
2013-09-03 19:54:27 +04:00
parent 173303104e
commit e3079ac667
26 changed files with 298 additions and 158 deletions
@@ -1,6 +1,8 @@
package org.jetbrains.jet.lang.types;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
@@ -8,10 +10,12 @@ import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class CastDiagnosticsUtil {
@@ -44,11 +48,8 @@ public class CastDiagnosticsUtil {
List<JetType> aTypes = mapToPlatformIndependentTypes(a, platformToKotlinClassMap);
List<JetType> bTypes = mapToPlatformIndependentTypes(b, platformToKotlinClassMap);
for (int i = 0; i < aTypes.size(); i++) {
JetType aType = aTypes.get(i);
for (int j = 0; j < bTypes.size(); j++) {
JetType bType = bTypes.get(j);
for (JetType aType : aTypes) {
for (JetType bType : bTypes) {
if (JetTypeChecker.INSTANCE.isSubtypeOf(aType, bType)) return true;
if (JetTypeChecker.INSTANCE.isSubtypeOf(bType, aType)) return true;
}
@@ -91,5 +92,82 @@ public class CastDiagnosticsUtil {
return descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.TRAIT;
}
/**
* Check if cast from supertype to subtype is erased.
* It is an error in "is" statement and warning in "as".
*/
public static boolean isCastErased(@NotNull JetType supertype, @NotNull JetType subtype, @NotNull JetTypeChecker typeChecker) {
// cast between T and T? is always OK
if (supertype.isNullable() || subtype.isNullable()) {
return isCastErased(TypeUtils.makeNotNullable(supertype), TypeUtils.makeNotNullable(subtype), typeChecker);
}
// if it is a upcast, it's never erased
if (typeChecker.isSubtypeOf(supertype, subtype)) return false;
// downcasting to a type parameter is always erased
if (isTypeParameter(subtype)) return true;
// Check that we are actually casting to a generic type
// NOTE: this does not account for 'as Array<List<T>>'
if (allParametersReified(subtype)) return false;
// Assume we are casting an expression of type Collection<Foo> to List<Bar>
// First, let's make List<T>, where T is a type variable
JetType subtypeWithVariables = TypeUtils.makeUnsubstitutedType(
subtype.getConstructor(),
ErrorUtils.createErrorScope("Scope for intermediate type. This type shouldn't be used outside isCastErased()", true));
// Now, let's find a supertype of List<T> that is a Collection of something,
// in this case it will be Collection<T>
JetType supertypeWithVariables = TypeCheckingProcedure.findCorrespondingSupertype(subtypeWithVariables, supertype);
if (supertypeWithVariables == null) return true;
// Now, let's try to unify Collection<T> and Collection<Foo>
// solution is a map from T to Foo
final List<TypeParameterDescriptor> variables = subtypeWithVariables.getConstructor().getParameters();
TypeUnifier.UnificationResult solution = TypeUnifier.unify(
new TypeProjection(supertype), new TypeProjection(supertypeWithVariables),
new Predicate<TypeConstructor>() {
@Override
public boolean apply(TypeConstructor typeConstructor) {
ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor();
return descriptor instanceof TypeParameterDescriptor && variables.contains(descriptor);
}
});
// If some of the parameters are not determined by unification, it means that these parameters are lost,
// let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as List<*>
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap(solution.getSubstitution());
for (TypeParameterDescriptor variable : variables) {
TypeProjection value = substitution.get(variable.getTypeConstructor());
if (value == null) {
substitution.put(
variable.getTypeConstructor(),
SubstitutionUtils.makeStarProjection(variable)
);
}
}
// At this point we have values for all type parameters of List
// Let's make a type by substituting them: List<T> -> List<Foo>
JetType staticallyKnownSubtype = TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT);
// If the substitution failed, it means that the result is an impossible type, e.g. something like Out<in Foo>
// In this case, we can't guarantee anything, so the cast is considered to be erased
if (staticallyKnownSubtype == null) return true;
// If the type we calculated is a subtype of the cast target, it's OK to use the cast target instead.
// If not, it's wrong to use it
return !typeChecker.isSubtypeOf(staticallyKnownSubtype, subtype);
}
private static boolean allParametersReified(JetType subtype) {
for (TypeParameterDescriptor parameterDescriptor : subtype.getConstructor().getParameters()) {
if (!parameterDescriptor.isReified()) return false;
}
return true;
}
private CastDiagnosticsUtil() {}
}
@@ -353,13 +353,18 @@ public class TypeUtils {
@NotNull
public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
if (ErrorUtils.isError(classDescriptor)) {
return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
return makeUnsubstitutedType(classDescriptor.getTypeConstructor(), unsubstitutedMemberScope);
}
@NotNull
public static JetType makeUnsubstitutedType(TypeConstructor typeConstructor, JetScope unsubstitutedMemberScope) {
if (ErrorUtils.isError(typeConstructor)) {
return ErrorUtils.createErrorType("Unsubstituted type for " + typeConstructor);
}
List<TypeProjection> arguments = getDefaultTypeProjections(classDescriptor.getTypeConstructor().getParameters());
List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classDescriptor.getTypeConstructor(),
typeConstructor,
false,
arguments,
unsubstitutedMemberScope
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.types.expressions;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
@@ -57,7 +56,6 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.utils.ThrowingList;
@@ -235,156 +233,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(USELESS_CAST.on(expression.getOperationReference()));
}
else {
if (isCastErased(actualType, targetType, typeChecker)) {
if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
}
}
}
}
/**
* Check if assignment from supertype to subtype is erased.
* It is an error in "is" statement and warning in "as".
*/
public static boolean isCastErased(@NotNull JetType supertype, @NotNull JetType subtype, @NotNull JetTypeChecker typeChecker) {
if (!(subtype.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
// TODO: what if it is TypeParameterDescriptor?
return false;
}
// do not crash on error types
if (ErrorUtils.isErrorType(supertype) || ErrorUtils.isErrorType(subtype)) {
return false;
}
return hasDowncastsInTypeArguments(supertype, subtype, typeChecker) || hasErasedTypeArguments(supertype, subtype);
}
/*
Check if type arguments are downcasted, which cannot be checked at run-time.
Examples:
1. a: MutableList<out Any> is MutableList<String> - true, because 'String' is more specific
2. a: Collection<String> is List<Any> - false, because 'Any' is less specific, and it is guaranteed by static checker
3. a: MutableCollection<String> is MutableList<Any> - false, because these types have empty intersection (type parameter is invariant)
*/
private static boolean hasDowncastsInTypeArguments(
@NotNull JetType supertype,
@NotNull JetType subtype,
@NotNull JetTypeChecker typeChecker
) {
List<TypeParameterDescriptor> superParameters = supertype.getConstructor().getParameters();
// This map holds arguments for type parameters of all superclasses of a type (see method comment for sample)
Multimap<TypeConstructor, TypeProjection> subtypeSubstitutionMap = SubstitutionUtils.buildDeepSubstitutionMultimap(subtype);
for (int i = 0; i < superParameters.size(); i++) {
TypeProjection superArgument = supertype.getArguments().get(i);
TypeParameterDescriptor parameter = superParameters.get(i);
if (parameter.isReified()) {
continue;
}
Collection<TypeProjection> substituted = subtypeSubstitutionMap.get(parameter.getTypeConstructor());
for (TypeProjection substitutedArgument : substituted) {
// For sample #2 (a: Collection<String> is List<Any>):
// parameter = E declared in Collection
// superArgument = String
// substitutedArgument = Any, because Collection<Any> is the supertype of List<Any>
// 1. Any..Nothing
// 2. String..Nothing
// 3. String..String
JetType superOut = TypeCheckingProcedure.getOutType(parameter, superArgument);
JetType superIn = TypeCheckingProcedure.getInType(parameter, superArgument);
// 1. String..String
// 2. Any..Nothing
// 3. Any..Any
JetType subOut = TypeCheckingProcedure.getOutType(parameter, substitutedArgument);
JetType subIn = TypeCheckingProcedure.getInType(parameter, substitutedArgument);
// super type range must be a subset of sub type range
if (typeChecker.isSubtypeOf(superOut, subOut) && typeChecker.isSubtypeOf(subIn, superIn)) {
// continue
}
else {
return true;
}
}
}
return false;
}
/*
Check if type arguments are erased, that is they are not mapped to type parameters of supertype's class
Examples (MyMap is defined like this: trait MyMap<T>: Map<String, T>):
1. a: Any is List<String> - true
2. a: Collection<CharSequence> is List<String> - false
3. a: Map<String, String> is MyMap<String> - false
*/
private static boolean hasErasedTypeArguments(
@NotNull JetType supertype,
@NotNull JetType subtype
) {
// Erase all type arguments, replacing them with unsubstituted versions:
// 1. List<E>
// 2. List<E>
// 3. MyMap<T>
JetType subtypeCleared = TypeUtils.makeUnsubstitutedType(
(ClassDescriptor) subtype.getConstructor().getDeclarationDescriptor(), null);
// This map holds arguments for type parameters of all superclasses of a type (see method comment for sample)
// For all "E" declared in Collection, Iterable, etc., value will be type "E", where the latter E is declared in List
Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap =
SubstitutionUtils.buildDeepSubstitutionMultimap(subtypeCleared);
// This set will contain all arguments for type parameters of superclass which are mapped from type parameters of subtype's class
// 1. empty
// 2. [E declared in List]
// 3. [T declared in MyMap]
Set<JetType> clearSubstituted = new HashSet<JetType>();
List<TypeParameterDescriptor> superParameters = supertype.getConstructor().getParameters();
for (TypeParameterDescriptor superParameter : superParameters) {
Collection<TypeProjection> substituted = clearTypeSubstitutionMap.get(superParameter.getTypeConstructor());
for (TypeProjection substitutedProjection : substituted) {
clearSubstituted.add(substitutedProjection.getType());
}
}
// For each type parameter of subtype's class, we check that it is mapped to type parameters of supertype,
// that is its type is present in clearSubstituted set
List<TypeParameterDescriptor> subParameters = subtype.getConstructor().getParameters();
for (int i = 0; i < subParameters.size(); i++) {
TypeParameterDescriptor parameter = subParameters.get(i);
TypeProjection argument = subtype.getArguments().get(i);
if (parameter.isReified()) {
continue;
}
// "is List<*>", no check for type argument, actually
if (argument.equals(SubstitutionUtils.makeStarProjection(parameter))) {
continue;
}
// if parameter is mapped to nothing then it is erased
// 1. return from here
// 2. contains = true, don't return
// 3. contains = true, don't return
if (!clearSubstituted.contains(parameter.getDefaultType())) {
return true;
}
}
return false;
}
@Override
public JetTypeInfo visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) {
JetType result = null;
@@ -285,7 +285,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(nullableType));
}
checkTypeCompatibility(context, type, subjectType, typeReferenceAfterIs);
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type));
}
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo);
@@ -0,0 +1,10 @@
trait Map<K, out V>
trait MutableMap<K, V>: Map<K, V> {
fun set(k: K, v: V)
}
fun p(p: Map<String, Int>) {
if (p is MutableMap<String, Int>) {
p[""] = 1
}
}
@@ -0,0 +1 @@
fun f(a: Array<out Number>) = a is Array<Int>
@@ -0,0 +1,5 @@
open class BaseTwo<A, B>
open class DerivedWithOne<D>: BaseTwo<D, String>()
// a is BaseTwo<T, U> => if (a is DerivedWithOne<?>) a is DerivedWithOne<T>
fun <T, U> testing(a: BaseTwo<T, U>) = a is DerivedWithOne<T>
@@ -0,0 +1,5 @@
open class Base<A>
class Some: Base<Int>()
// a is Some => a is Base<Int>
fun f(a: Some) = a is Base<Int>
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class Base<out T>
open class SubBase<T> : Base<T>()
// l is Base<+B> => if (l is SubBase<?>) l is SubBase<+B> => l is SubBase<+A>
fun ff(l: Base<B>) = l is SubBase<out A>
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class Base<in T>
class SubBase: Base<A>()
// f is SubBase => f is Base<A> => (Base<Contravariant T>, B <: A) f is Base<B>
fun test(f: SubBase) = f is Base<B>
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class Base<out T>
class SubBase: Base<B>()
// f is SubBase => (SubBase <: Base<B>) f is Base<B> => (B <: A, Base<Covariant T> => SubBase <: Base<A>) f is Base<A>
fun test(f: SubBase) = f is Base<A>
@@ -0,0 +1,9 @@
trait A
trait B: A
trait D
trait BaseSuper<T>
trait BaseImpl: BaseSuper<D>
trait DerivedSuper<out S>: <!INCONSISTENT_TYPE_PARAMETER_VALUES!>BaseSuper<S>, BaseImpl<!>
fun test(t: BaseSuper<B>) = t is DerivedSuper<A>
@@ -0,0 +1,6 @@
open class BaseMulti<out A, B>
class SomeMultiDerived<out D>: BaseMulti<D, Any>()
// t is BaseMulti<+String, String> => if (t is SomeMultiDerived<?>) => t is SomeMultiDerived<+String> =>
// => (String <: Any, SomeMultiDerived<Covariant D>) t is SomeMultiDerived<+Any>
fun someDerived(t: BaseMulti<String, String>) = t is SomeMultiDerived<Any>
@@ -0,0 +1,5 @@
open class Base<A>
class Some: Base<Int>()
// No erased types in check
fun <A> f(a: Base<A>) = a is Some
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class Base<out T>
open class SubBase<T> : Base<T>()
fun ff(l: Base<B>) = l is <!CANNOT_CHECK_FOR_ERASED!>SubBase<A><!>
@@ -0,0 +1,6 @@
trait A
trait B: A
trait Base<T>
fun <T> test(a: Base<B>) where T: Base<A> = a is <!CANNOT_CHECK_FOR_ERASED!>T<!>
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class D
open class Base<out T, out U>
open class Derived<out S>: Base<S, S>()
fun test(a: Base<D, B>) = a is <!CANNOT_CHECK_FOR_ERASED!>Derived<A><!>
@@ -0,0 +1,8 @@
open class A
open class B: A()
open class D
open class Base<out T, out U>
open class Derived<out S>: Base<S, S>()
fun test(a: Base<B, D>) = a is <!CANNOT_CHECK_FOR_ERASED!>Derived<A><!>
@@ -0,0 +1,3 @@
trait A
trait B
fun testing(a: A) = a as B
@@ -0,0 +1 @@
fun <T: Any> testing(a: T?) = a is T
@@ -0,0 +1 @@
fun <T> testing(a: T) = a is T
@@ -0,0 +1 @@
fun testing(a: Any) = a is <!UNRESOLVED_REFERENCE!>UnresolvedType<!><Int>
@@ -0,0 +1,6 @@
open class RecA<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecB<T><!>()
open class RecB<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>RecA<T><!>()
open class SelfR<T>: <!CYCLIC_INHERITANCE_HIERARCHY!>SelfR<T><!>()
fun test(f: SelfR<String>) = f is <!CANNOT_CHECK_FOR_ERASED!>RecA<String><!>
fun test(f: RecB<String>) = f is RecA<String>
@@ -6,7 +6,7 @@ public fun foo(a: Any) {
a is Map<out Any?, Any?>
a is Map<*, *>
a is Map<<!SYNTAX!><!>>
a is <!CANNOT_CHECK_FOR_ERASED!>List<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Map<!>><!>
a is List<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Map<!>>
a is <!NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION!>List<!>
a is Int
@@ -5,7 +5,7 @@ public fun foo(a: Any, <!UNUSED_PARAMETER!>b<!>: <!WRONG_NUMBER_OF_TYPE_ARGUMENT
is Map<out Any?, Any?> -> {}
is Map<*, *> -> {}
is Map<<!SYNTAX!><!>> -> {}
is <!CANNOT_CHECK_FOR_ERASED!>List<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Map<!>><!> -> {}
is List<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Map<!>> -> {}
is <!NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION!>List<!> -> {}
is Int -> {}
else -> {}
@@ -980,6 +980,56 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/cast/AsErasedWarning.kt");
}
@TestMetadata("DowncastMap.kt")
public void testDowncastMap() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/DowncastMap.kt");
}
@TestMetadata("IsArray.kt")
public void testIsArray() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsArray.kt");
}
@TestMetadata("IsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric.kt")
public void testIsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForDerivedWithOneSubstitutedAndOneSameGeneric.kt");
}
@TestMetadata("IsErasedAllowForExactSupertypeCheck.kt")
public void testIsErasedAllowForExactSupertypeCheck() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForExactSupertypeCheck.kt");
}
@TestMetadata("IsErasedAllowForOverridenVarianceWithProjection.kt")
public void testIsErasedAllowForOverridenVarianceWithProjection() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForOverridenVarianceWithProjection.kt");
}
@TestMetadata("IsErasedAllowForSupertypeCheckWithContrvariance.kt")
public void testIsErasedAllowForSupertypeCheckWithContrvariance() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForSupertypeCheckWithContrvariance.kt");
}
@TestMetadata("IsErasedAllowForSupertypeCheckWithCovariance.kt")
public void testIsErasedAllowForSupertypeCheckWithCovariance() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForSupertypeCheckWithCovariance.kt");
}
@TestMetadata("IsErasedAllowForTypeWithIrrelevantMixin.kt")
public void testIsErasedAllowForTypeWithIrrelevantMixin() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithIrrelevantMixin.kt");
}
@TestMetadata("IsErasedAllowForTypeWithTwoSameTypeSubstitutions.kt")
public void testIsErasedAllowForTypeWithTwoSameTypeSubstitutions() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithTwoSameTypeSubstitutions.kt");
}
@TestMetadata("IsErasedAllowForTypeWithoutTypeArguments.kt")
public void testIsErasedAllowForTypeWithoutTypeArguments() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowForTypeWithoutTypeArguments.kt");
}
@TestMetadata("IsErasedAllowFromOut.kt")
public void testIsErasedAllowFromOut() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedAllowFromOut.kt");
@@ -1015,6 +1065,16 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowDifferentArgInvariantPosition.kt");
}
@TestMetadata("IsErasedDisallowForOverridenVariance.kt")
public void testIsErasedDisallowForOverridenVariance() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowForOverridenVariance.kt");
}
@TestMetadata("IsErasedDisallowForTypeWithConstraints.kt")
public void testIsErasedDisallowForTypeWithConstraints() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowForTypeWithConstraints.kt");
}
@TestMetadata("IsErasedDisallowFromAny.kt")
public void testIsErasedDisallowFromAny() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowFromAny.kt");
@@ -1035,11 +1095,46 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDisallowFromOutAtClass.kt");
}
@TestMetadata("IsErasedDissallowForSubtypeMappedToTwoParamsWithFirstInvalid.kt")
public void testIsErasedDissallowForSubtypeMappedToTwoParamsWithFirstInvalid() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDissallowForSubtypeMappedToTwoParamsWithFirstInvalid.kt");
}
@TestMetadata("IsErasedDissallowForSubtypeMappedToTwoParamsWithSecondInvalid.kt")
public void testIsErasedDissallowForSubtypeMappedToTwoParamsWithSecondInvalid() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedDissallowForSubtypeMappedToTwoParamsWithSecondInvalid.kt");
}
@TestMetadata("IsErasedNonGeneric.kt")
public void testIsErasedNonGeneric() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedNonGeneric.kt");
}
@TestMetadata("IsErasedNullableTasT.kt")
public void testIsErasedNullableTasT() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedNullableTasT.kt");
}
@TestMetadata("IsErasedStar.kt")
public void testIsErasedStar() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedStar.kt");
}
@TestMetadata("IsErasedTasT.kt")
public void testIsErasedTasT() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedTasT.kt");
}
@TestMetadata("IsErasedToErrorType.kt")
public void testIsErasedToErrorType() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsErasedToErrorType.kt");
}
@TestMetadata("IsRecursionSustainable.kt")
public void testIsRecursionSustainable() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsRecursionSustainable.kt");
}
@TestMetadata("IsReified.kt")
public void testIsReified() throws Exception {
doTest("compiler/testData/diagnostics/tests/cast/IsReified.kt");