Erased casts supported
This commit is contained in:
@@ -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
|
||||
|
||||
+1
-146
@@ -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;
|
||||
|
||||
+1
-1
@@ -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>
|
||||
+5
@@ -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>
|
||||
+8
@@ -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>
|
||||
+8
@@ -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>
|
||||
+8
@@ -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>
|
||||
+6
@@ -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<!>
|
||||
+8
@@ -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><!>
|
||||
+8
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user