Allow bare types on the right-hand side of as/as?/is/!is
This commit is contained in:
@@ -0,0 +1,99 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bare types are somewhat like raw types, but in Kotlin they are only allowed on the right-hand side of is/as.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* fun foo(a: Any) {
|
||||||
|
* if (a is List) {
|
||||||
|
* // a is known to be List<*> here
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Another example:
|
||||||
|
*
|
||||||
|
* fun foo(a: Collection<String>) {
|
||||||
|
* if (a is List) {
|
||||||
|
* // a is known to be List<String> here
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* One can call reconstruct(supertype) to get an actual type from a bare type
|
||||||
|
*/
|
||||||
|
public class PossiblyBareType {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PossiblyBareType bare(@NotNull TypeConstructor bareTypeConstructor, boolean nullable) {
|
||||||
|
return new PossiblyBareType(null, bareTypeConstructor, nullable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PossiblyBareType type(@NotNull JetType actualType) {
|
||||||
|
return new PossiblyBareType(actualType, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final JetType actualType;
|
||||||
|
private final TypeConstructor bareTypeConstructor;
|
||||||
|
private final boolean nullable;
|
||||||
|
|
||||||
|
private PossiblyBareType(@Nullable JetType actualType, @Nullable TypeConstructor bareTypeConstructor, boolean nullable) {
|
||||||
|
this.actualType = actualType;
|
||||||
|
this.bareTypeConstructor = bareTypeConstructor;
|
||||||
|
this.nullable = nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBare() {
|
||||||
|
return actualType == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getActualType() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return actualType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TypeConstructor getBareTypeConstructor() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return bareTypeConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBareTypeNullable() {
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNullable() {
|
||||||
|
if (isBare()) return isBareTypeNullable();
|
||||||
|
return getActualType().isNullable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PossiblyBareType makeNullable() {
|
||||||
|
if (isBare()) {
|
||||||
|
return isBareTypeNullable() ? this : bare(getBareTypeConstructor(), true);
|
||||||
|
}
|
||||||
|
return type(TypeUtils.makeNullable(getActualType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType reconstruct(@NotNull JetType subjectType) {
|
||||||
|
if (!isBare()) return getActualType();
|
||||||
|
|
||||||
|
JetType type = CastDiagnosticsUtil.findStaticallyKnownSubtype(
|
||||||
|
TypeUtils.makeNotNullable(subjectType),
|
||||||
|
getBareTypeConstructor()
|
||||||
|
);
|
||||||
|
// No need to make an absent type nullable
|
||||||
|
if (type == null) return type;
|
||||||
|
|
||||||
|
return TypeUtils.makeNullableAsSpecified(type, isBareTypeNullable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return isBare() ? "bare " + bareTypeConstructor + (isBareTypeNullable() ? "?" : "") : getActualType().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,16 @@ public class TypeResolutionContext {
|
|||||||
public final JetScope scope;
|
public final JetScope scope;
|
||||||
public final BindingTrace trace;
|
public final BindingTrace trace;
|
||||||
public final boolean checkBounds;
|
public final boolean checkBounds;
|
||||||
|
public final boolean allowBareTypes;
|
||||||
|
|
||||||
public TypeResolutionContext(@NotNull JetScope scope, @NotNull BindingTrace trace, boolean checkBounds) {
|
public TypeResolutionContext(@NotNull JetScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes) {
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.checkBounds = checkBounds;
|
this.checkBounds = checkBounds;
|
||||||
|
this.allowBareTypes = allowBareTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeResolutionContext noBareTypes() {
|
||||||
|
return new TypeResolutionContext(scope, trace, checkBounds, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -35,6 +34,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.PossiblyBareType.type;
|
||||||
import static org.jetbrains.jet.lang.types.Variance.*;
|
import static org.jetbrains.jet.lang.types.Variance.*;
|
||||||
|
|
||||||
public class TypeResolver {
|
public class TypeResolver {
|
||||||
@@ -60,32 +60,41 @@ public class TypeResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
|
public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
|
||||||
return resolveType(new TypeResolutionContext(scope, trace, checkBounds), typeReference);
|
// bare types are not allowed
|
||||||
|
return resolveType(new TypeResolutionContext(scope, trace, checkBounds, false), typeReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetType resolveType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
|
public JetType resolveType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
|
||||||
|
assert !c.allowBareTypes : "Use resolvePossiblyBareType() when bare types are allowed";
|
||||||
|
return resolvePossiblyBareType(c, typeReference).getActualType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PossiblyBareType resolvePossiblyBareType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
|
||||||
JetType cachedType = c.trace.getBindingContext().get(BindingContext.TYPE, typeReference);
|
JetType cachedType = c.trace.getBindingContext().get(BindingContext.TYPE, typeReference);
|
||||||
if (cachedType != null) return cachedType;
|
if (cachedType != null) return type(cachedType);
|
||||||
|
|
||||||
List<AnnotationDescriptor> annotations = annotationResolver.getResolvedAnnotations(typeReference.getAnnotations(), c.trace);
|
List<AnnotationDescriptor> annotations = annotationResolver.getResolvedAnnotations(typeReference.getAnnotations(), c.trace);
|
||||||
|
|
||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
JetType type = resolveTypeElement(c, annotations, typeElement);
|
PossiblyBareType type = resolveTypeElement(c, annotations, typeElement);
|
||||||
c.trace.record(BindingContext.TYPE, typeReference, type);
|
if (!type.isBare()) {
|
||||||
|
c.trace.record(BindingContext.TYPE, typeReference, type.getActualType());
|
||||||
|
}
|
||||||
c.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, c.scope);
|
c.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, c.scope);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JetType resolveTypeElement(
|
private PossiblyBareType resolveTypeElement(
|
||||||
final TypeResolutionContext c,
|
final TypeResolutionContext c,
|
||||||
final List<AnnotationDescriptor> annotations,
|
final List<AnnotationDescriptor> annotations,
|
||||||
JetTypeElement typeElement
|
JetTypeElement typeElement
|
||||||
) {
|
) {
|
||||||
|
|
||||||
final JetType[] result = new JetType[1];
|
final PossiblyBareType[] result = new PossiblyBareType[1];
|
||||||
if (typeElement != null) {
|
if (typeElement != null) {
|
||||||
typeElement.accept(new JetVisitorVoid() {
|
typeElement.accept(new JetVisitorVoid() {
|
||||||
@Override
|
@Override
|
||||||
@@ -109,16 +118,16 @@ public class TypeResolver {
|
|||||||
|
|
||||||
JetScope scopeForTypeParameter = getScopeForTypeParameter(c, typeParameterDescriptor);
|
JetScope scopeForTypeParameter = getScopeForTypeParameter(c, typeParameterDescriptor);
|
||||||
if (scopeForTypeParameter instanceof ErrorUtils.ErrorScope) {
|
if (scopeForTypeParameter instanceof ErrorUtils.ErrorScope) {
|
||||||
result[0] = ErrorUtils.createErrorType("?");
|
result[0] = type(ErrorUtils.createErrorType("?"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result[0] = new JetTypeImpl(
|
result[0] = type(new JetTypeImpl(
|
||||||
annotations,
|
annotations,
|
||||||
typeParameterDescriptor.getTypeConstructor(),
|
typeParameterDescriptor.getTypeConstructor(),
|
||||||
TypeUtils.hasNullableLowerBound(typeParameterDescriptor),
|
TypeUtils.hasNullableLowerBound(typeParameterDescriptor),
|
||||||
Collections.<TypeProjection>emptyList(),
|
Collections.<TypeProjection>emptyList(),
|
||||||
scopeForTypeParameter
|
scopeForTypeParameter
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
|
||||||
@@ -138,32 +147,33 @@ public class TypeResolver {
|
|||||||
int expectedArgumentCount = parameters.size();
|
int expectedArgumentCount = parameters.size();
|
||||||
int actualArgumentCount = arguments.size();
|
int actualArgumentCount = arguments.size();
|
||||||
if (ErrorUtils.isError(typeConstructor)) {
|
if (ErrorUtils.isError(typeConstructor)) {
|
||||||
result[0] = ErrorUtils.createErrorType("[Error type: " + typeConstructor + "]");
|
result[0] = type(ErrorUtils.createErrorType("[Error type: " + typeConstructor + "]"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (actualArgumentCount != expectedArgumentCount) {
|
if (actualArgumentCount != expectedArgumentCount) {
|
||||||
if (actualArgumentCount == 0) {
|
if (actualArgumentCount == 0) {
|
||||||
if (rhsOfIsExpression(type) || rhsOfIsPattern(type)) {
|
// See docs for PossiblyBareType
|
||||||
c.trace.report(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION.on(type, expectedArgumentCount, allStarProjectionsString(typeConstructor)));
|
if (c.allowBareTypes) {
|
||||||
}
|
result[0] = PossiblyBareType.bare(typeConstructor, false);
|
||||||
else {
|
return;
|
||||||
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
|
|
||||||
}
|
}
|
||||||
|
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
|
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result[0] = new JetTypeImpl(
|
JetTypeImpl resultingType = new JetTypeImpl(
|
||||||
annotations,
|
annotations,
|
||||||
typeConstructor,
|
typeConstructor,
|
||||||
false,
|
false,
|
||||||
arguments,
|
arguments,
|
||||||
classDescriptor.getMemberScope(arguments)
|
classDescriptor.getMemberScope(arguments)
|
||||||
);
|
);
|
||||||
|
result[0] = type(resultingType);
|
||||||
if (c.checkBounds) {
|
if (c.checkBounds) {
|
||||||
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
|
TypeSubstitutor substitutor = TypeSubstitutor.create(resultingType);
|
||||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||||
TypeParameterDescriptor parameter = parameters.get(i);
|
TypeParameterDescriptor parameter = parameters.get(i);
|
||||||
JetType argument = arguments.get(i).getType();
|
JetType argument = arguments.get(i).getType();
|
||||||
@@ -181,35 +191,35 @@ public class TypeResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNullableType(JetNullableType nullableType) {
|
public void visitNullableType(JetNullableType nullableType) {
|
||||||
JetType baseType = resolveTypeElement(c, annotations, nullableType.getInnerType());
|
PossiblyBareType baseType = resolveTypeElement(c, annotations, nullableType.getInnerType());
|
||||||
if (baseType.isNullable()) {
|
if (baseType.isNullable()) {
|
||||||
c.trace.report(REDUNDANT_NULLABLE.on(nullableType));
|
c.trace.report(REDUNDANT_NULLABLE.on(nullableType));
|
||||||
}
|
}
|
||||||
else if (TypeUtils.hasNullableSuperType(baseType)) {
|
else if (!baseType.isBare() && TypeUtils.hasNullableSuperType(baseType.getActualType())) {
|
||||||
c.trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType));
|
c.trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType.getActualType()));
|
||||||
}
|
}
|
||||||
result[0] = TypeUtils.makeNullable(baseType);
|
result[0] = baseType.makeNullable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitFunctionType(JetFunctionType type) {
|
public void visitFunctionType(JetFunctionType type) {
|
||||||
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
||||||
JetType receiverType = receiverTypeRef == null ? null : resolveType(c, receiverTypeRef);
|
JetType receiverType = receiverTypeRef == null ? null : resolveType(c.noBareTypes(), receiverTypeRef);
|
||||||
|
|
||||||
List<JetType> parameterTypes = new ArrayList<JetType>();
|
List<JetType> parameterTypes = new ArrayList<JetType>();
|
||||||
for (JetParameter parameter : type.getParameters()) {
|
for (JetParameter parameter : type.getParameters()) {
|
||||||
parameterTypes.add(resolveType(c, parameter.getTypeReference()));
|
parameterTypes.add(resolveType(c.noBareTypes(), parameter.getTypeReference()));
|
||||||
}
|
}
|
||||||
|
|
||||||
JetTypeReference returnTypeRef = type.getReturnTypeRef();
|
JetTypeReference returnTypeRef = type.getReturnTypeRef();
|
||||||
JetType returnType;
|
JetType returnType;
|
||||||
if (returnTypeRef != null) {
|
if (returnTypeRef != null) {
|
||||||
returnType = resolveType(c, returnTypeRef);
|
returnType = resolveType(c.noBareTypes(), returnTypeRef);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
returnType = KotlinBuiltIns.getInstance().getUnitType();
|
returnType = KotlinBuiltIns.getInstance().getUnitType();
|
||||||
}
|
}
|
||||||
result[0] = KotlinBuiltIns.getInstance().getFunctionType(annotations, receiverType, parameterTypes, returnType);
|
result[0] = type(KotlinBuiltIns.getInstance().getFunctionType(annotations, receiverType, parameterTypes, returnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,32 +229,11 @@ public class TypeResolver {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (result[0] == null) {
|
if (result[0] == null) {
|
||||||
return ErrorUtils.createErrorType(typeElement == null ? "No type element" : typeElement.getText());
|
return type(ErrorUtils.createErrorType(typeElement == null ? "No type element" : typeElement.getText()));
|
||||||
}
|
}
|
||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean rhsOfIsExpression(@NotNull JetUserType type) {
|
|
||||||
// Look for the FIRST expression containing this type
|
|
||||||
JetExpression outerExpression = PsiTreeUtil.getParentOfType(type, JetExpression.class);
|
|
||||||
if (outerExpression instanceof JetIsExpression) {
|
|
||||||
JetIsExpression isExpression = (JetIsExpression) outerExpression;
|
|
||||||
// If this expression is JetIsExpression, and the type is the outermost on the RHS
|
|
||||||
if (type.getParent() == isExpression.getTypeRef()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean rhsOfIsPattern(@NotNull JetUserType type) {
|
|
||||||
// Look for the is-pattern containing this type
|
|
||||||
JetWhenConditionIsPattern outerPattern = PsiTreeUtil.getParentOfType(type, JetWhenConditionIsPattern.class, false, JetExpression.class);
|
|
||||||
if (outerPattern == null) return false;
|
|
||||||
// We are interested only in the outermost type on the RHS
|
|
||||||
return type.getParent() == outerPattern.getTypeRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
private JetScope getScopeForTypeParameter(TypeResolutionContext c, final TypeParameterDescriptor typeParameterDescriptor) {
|
private JetScope getScopeForTypeParameter(TypeResolutionContext c, final TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
if (c.checkBounds) {
|
if (c.checkBounds) {
|
||||||
return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
|
return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
|
||||||
@@ -283,7 +272,7 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO : handle the Foo<in *> case
|
// TODO : handle the Foo<in *> case
|
||||||
type = resolveType(c, argumentElement.getTypeReference());
|
type = resolveType(c.noBareTypes(), argumentElement.getTypeReference());
|
||||||
Variance kind = resolveProjectionKind(projectionKind);
|
Variance kind = resolveProjectionKind(projectionKind);
|
||||||
if (constructor.getParameters().size() > i) {
|
if (constructor.getParameters().size() > i) {
|
||||||
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
||||||
@@ -333,15 +322,4 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String allStarProjectionsString(@NotNull TypeConstructor constructor) {
|
|
||||||
int size = constructor.getParameters().size();
|
|
||||||
assert size != 0 : "No projections possible for a nilary type constructor" + constructor;
|
|
||||||
ClassifierDescriptor declarationDescriptor = constructor.getDeclarationDescriptor();
|
|
||||||
assert declarationDescriptor != null : "No declaration descriptor for type constructor " + constructor;
|
|
||||||
String name = declarationDescriptor.getName().asString();
|
|
||||||
|
|
||||||
return TypeUtils.getTypeNameAndStarProjectionsString(name, size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,11 +112,41 @@ public class CastDiagnosticsUtil {
|
|||||||
// NOTE: this does not account for 'as Array<List<T>>'
|
// NOTE: this does not account for 'as Array<List<T>>'
|
||||||
if (allParametersReified(subtype)) return false;
|
if (allParametersReified(subtype)) return false;
|
||||||
|
|
||||||
|
JetType staticallyKnownSubtype = findStaticallyKnownSubtype(supertype, subtype.getConstructor());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remember that we are trying to cast something of type {@code supertype} to {@code subtype}.
|
||||||
|
*
|
||||||
|
* Since at runtime we can only check the class (type constructor), the rest of the subtype should be known statically, from supertype.
|
||||||
|
* This method reconstructs all static information that can be obtained from supertype.
|
||||||
|
*
|
||||||
|
* Example 1:
|
||||||
|
* supertype = Collection<String>
|
||||||
|
* subtype = List<...>
|
||||||
|
* result = List<String>
|
||||||
|
*
|
||||||
|
* Example 2:
|
||||||
|
* supertype = Any
|
||||||
|
* subtype = List<...>
|
||||||
|
* result = List<*>
|
||||||
|
*/
|
||||||
|
public static JetType findStaticallyKnownSubtype(@NotNull JetType supertype, @NotNull TypeConstructor subtypeConstructor) {
|
||||||
|
assert !supertype.isNullable() : "This method only makes sense for non-nullable types";
|
||||||
|
|
||||||
// Assume we are casting an expression of type Collection<Foo> to List<Bar>
|
// 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
|
// First, let's make List<T>, where T is a type variable
|
||||||
JetType subtypeWithVariables = TypeUtils.makeUnsubstitutedType(
|
ClassifierDescriptor descriptor = subtypeConstructor.getDeclarationDescriptor();
|
||||||
subtype.getConstructor(),
|
assert descriptor != null : "Can't create default type for " + subtypeConstructor;
|
||||||
ErrorUtils.createErrorScope("Scope for intermediate type. This type shouldn't be used outside isCastErased()", true));
|
JetType subtypeWithVariables = descriptor.getDefaultType();
|
||||||
|
|
||||||
// Now, let's find a supertype of List<T> that is a Collection of something,
|
// Now, let's find a supertype of List<T> that is a Collection of something,
|
||||||
// in this case it will be Collection<T>
|
// in this case it will be Collection<T>
|
||||||
@@ -158,15 +188,7 @@ public class CastDiagnosticsUtil {
|
|||||||
|
|
||||||
// At this point we have values for all type parameters of List
|
// At this point we have values for all type parameters of List
|
||||||
// Let's make a type by substituting them: List<T> -> List<Foo>
|
// Let's make a type by substituting them: List<T> -> List<Foo>
|
||||||
JetType staticallyKnownSubtype = TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT);
|
return 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) {
|
private static boolean allParametersReified(JetType subtype) {
|
||||||
|
|||||||
+26
-6
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.types.expressions;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
|
import com.intellij.psi.tree.TokenSet;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
@@ -76,10 +77,13 @@ import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
|
|||||||
import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
|
import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
|
||||||
import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.resolveSpecialConstructionAsCall;
|
import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.resolveSpecialConstructionAsCall;
|
||||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
|
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
|
||||||
|
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||||
|
|
||||||
@SuppressWarnings("SuspiciousMethodCalls")
|
@SuppressWarnings("SuspiciousMethodCalls")
|
||||||
public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||||
|
|
||||||
|
private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS);
|
||||||
|
|
||||||
private final PlatformToKotlinClassMap platformToKotlinClassMap;
|
private final PlatformToKotlinClassMap platformToKotlinClassMap;
|
||||||
|
|
||||||
protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade, @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
|
protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade, @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
|
||||||
@@ -167,10 +171,17 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
|
return JetTypeInfo.create(null, leftTypeInfo.getDataFlowInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType targetType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, right, context.trace, true);
|
|
||||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||||
|
|
||||||
|
boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
|
||||||
|
TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, allowBareTypes);
|
||||||
|
PossiblyBareType possiblyBareTarget = context.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, right);
|
||||||
|
|
||||||
if (isTypeFlexible(left) || operationType == JetTokens.COLON) {
|
if (isTypeFlexible(left) || operationType == JetTokens.COLON) {
|
||||||
|
// We do not allow bare types on static assertions, because static assertions provide an expected type for their argument,
|
||||||
|
// thus causing a circularity in type dependencies
|
||||||
|
assert !possiblyBareTarget.isBare() : "Bare types should not be allowed for static assertions, because argument inference makes no sense there";
|
||||||
|
JetType targetType = possiblyBareTarget.getActualType();
|
||||||
|
|
||||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
|
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType.replaceExpectedType(targetType));
|
||||||
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
|
checkBinaryWithTypeRHS(expression, context, targetType, typeInfo.getType());
|
||||||
@@ -180,15 +191,24 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
JetTypeInfo typeInfo = facade.getTypeInfo(left, contextWithNoExpectedType);
|
||||||
|
|
||||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||||
if (typeInfo.getType() != null) {
|
JetType subjectType = typeInfo.getType();
|
||||||
checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, typeInfo.getType());
|
JetType targetType;
|
||||||
|
if (subjectType != null) {
|
||||||
|
targetType = possiblyBareTarget.reconstruct(subjectType);
|
||||||
|
|
||||||
|
checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType);
|
||||||
dataFlowInfo = typeInfo.getDataFlowInfo();
|
dataFlowInfo = typeInfo.getDataFlowInfo();
|
||||||
if (operationType == JetTokens.AS_KEYWORD) {
|
if (operationType == AS_KEYWORD) {
|
||||||
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext());
|
DataFlowValue value =
|
||||||
|
DataFlowValueFactory.INSTANCE.createDataFlowValue(left, subjectType, context.trace.getBindingContext());
|
||||||
dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
|
dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JetType result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
else {
|
||||||
|
// Recovery: let's reconstruct as if we were casting from Any, to get some type there
|
||||||
|
targetType = possiblyBareTarget.reconstruct(KotlinBuiltIns.getInstance().getAnyType());
|
||||||
|
}
|
||||||
|
JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType;
|
||||||
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
return DataFlowUtils.checkType(result, expression, context, dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -23,6 +23,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.PossiblyBareType;
|
||||||
|
import org.jetbrains.jet.lang.resolve.TypeResolutionContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||||
@@ -279,8 +281,12 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (typeReferenceAfterIs == null) {
|
if (typeReferenceAfterIs == null) {
|
||||||
return noChange(context);
|
return noChange(context);
|
||||||
}
|
}
|
||||||
JetType type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReferenceAfterIs, context.trace,
|
TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true);
|
||||||
true);
|
PossiblyBareType possiblyBareTarget = context.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs);
|
||||||
|
JetType type = possiblyBareTarget.reconstruct(subjectType);
|
||||||
|
if (possiblyBareTarget.isBare()) {
|
||||||
|
context.trace.record(BindingContext.TYPE, typeReferenceAfterIs, type);
|
||||||
|
}
|
||||||
if (!subjectType.isNullable() && type.isNullable()) {
|
if (!subjectType.isNullable() && type.isNullable()) {
|
||||||
JetTypeElement element = typeReferenceAfterIs.getTypeElement();
|
JetTypeElement element = typeReferenceAfterIs.getTypeElement();
|
||||||
assert element instanceof JetNullableType : "element must be instance of " + JetNullableType.class.getName();
|
assert element instanceof JetNullableType : "element must be instance of " + JetNullableType.class.getName();
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
trait Tr
|
||||||
|
trait G<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr): Any {
|
||||||
|
return tr as G<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test1(tr: Tr): Any {
|
||||||
|
return tr as <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>.(<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>) -> <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
trait Tr<T>
|
||||||
|
trait G<T> : Tr<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr<String>) {
|
||||||
|
val v = tr as G?
|
||||||
|
// If v is not nullable, there will be a warning on this line:
|
||||||
|
v!!: G<String>
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
trait Either<out A, out B>
|
||||||
|
trait Left<out A>: Either<A, Nothing>
|
||||||
|
trait Right<out B>: Either<Nothing, B>
|
||||||
|
|
||||||
|
class C1(val v1: Int)
|
||||||
|
class C2(val v2: Int)
|
||||||
|
|
||||||
|
fun _as_left(e: Either<C1, C2>): Any {
|
||||||
|
val v = e as Left
|
||||||
|
return v: Left<C1>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun _as_right(e: Either<C1, C2>): Any {
|
||||||
|
val v = e as Right
|
||||||
|
return v: Right<C2>
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
trait Either<out A, out B>
|
||||||
|
trait Left<out A>: Either<A, Nothing> {
|
||||||
|
val value: A
|
||||||
|
}
|
||||||
|
trait Right<out B>: Either<Nothing, B> {
|
||||||
|
val value: B
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1(val v1: Int)
|
||||||
|
class C2(val v2: Int)
|
||||||
|
|
||||||
|
fun _is_l(e: Either<C1, C2>): Any {
|
||||||
|
if (e is Left) {
|
||||||
|
return e.value.v1
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
fun _is_r(e: Either<C1, C2>): Any {
|
||||||
|
if (e is Right) {
|
||||||
|
return e.value.v2
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
trait Either<out A, out B>
|
||||||
|
trait Left<out A>: Either<A, Nothing> {
|
||||||
|
val value: A
|
||||||
|
}
|
||||||
|
trait Right<out B>: Either<Nothing, B> {
|
||||||
|
val value: B
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1(val v1: Int)
|
||||||
|
class C2(val v2: Int)
|
||||||
|
|
||||||
|
fun _is_l(e: Either<C1, C2>): Any {
|
||||||
|
if (e !is Left) {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return e.value.v1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun _is_r(e: Either<C1, C2>): Any {
|
||||||
|
if (e !is Right) {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return e.value.v2
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
trait Either<out A, out B>
|
||||||
|
trait Left<out A>: Either<A, Nothing>
|
||||||
|
trait Right<out B>: Either<Nothing, B>
|
||||||
|
|
||||||
|
class C1(val v1: Int)
|
||||||
|
class C2(val v2: Int)
|
||||||
|
|
||||||
|
fun _as_left(e: Either<C1, C2>): Any? {
|
||||||
|
val v = e as? Left
|
||||||
|
return v: Left<C1>?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun _as_right(e: Either<C1, C2>): Any? {
|
||||||
|
val v = e as? Right
|
||||||
|
return v: Right<C2>?
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
trait Either<out A, out B>
|
||||||
|
trait Left<out A>: Either<A, Nothing> {
|
||||||
|
val value: A
|
||||||
|
}
|
||||||
|
trait Right<out B>: Either<Nothing, B> {
|
||||||
|
val value: B
|
||||||
|
}
|
||||||
|
|
||||||
|
class C1(val v1: Int)
|
||||||
|
class C2(val v2: Int)
|
||||||
|
|
||||||
|
fun _when(e: Either<C1, C2>): Any {
|
||||||
|
return when (e) {
|
||||||
|
is Left -> e.value.v1
|
||||||
|
is Right -> e.value.v2
|
||||||
|
else -> e
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
trait B<T>
|
||||||
|
trait G<T>: B<T>
|
||||||
|
|
||||||
|
fun f(p: B<<!UNRESOLVED_REFERENCE!>Foo<!>>): Any {
|
||||||
|
val v = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>p<!> as G
|
||||||
|
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>v<!>: G<*>
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
trait Tr<T>
|
||||||
|
trait G<T> : Tr<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr<String>?) {
|
||||||
|
val v = tr as G
|
||||||
|
v: G<String>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
trait B<T>
|
||||||
|
class G<T>: B<T>
|
||||||
|
|
||||||
|
fun f(b: B<String>?) = b is G?<!REDUNDANT_NULLABLE!>?<!>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
class P
|
||||||
|
|
||||||
|
fun foo(p: P): Any {
|
||||||
|
val v = p <!USELESS_CAST!>as<!> <!UNRESOLVED_REFERENCE!>G<!>
|
||||||
|
return <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>v<!>
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
trait Tr
|
||||||
|
trait G<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr) {
|
||||||
|
val v = tr as G
|
||||||
|
v: G<*>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
trait Tr
|
||||||
|
trait G<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr) = tr: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
trait Tr
|
||||||
|
trait G<T>
|
||||||
|
|
||||||
|
fun test(tr: Tr) = tr is G
|
||||||
@@ -964,7 +964,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/cast")
|
@TestMetadata("compiler/testData/diagnostics/tests/cast")
|
||||||
@InnerTestClasses({Cast.NeverSucceeds.class})
|
@InnerTestClasses({Cast.Bare.class, Cast.NeverSucceeds.class})
|
||||||
public static class Cast extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class Cast extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInCast() throws Exception {
|
public void testAllFilesPresentInCast() throws Exception {
|
||||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/cast"), Pattern.compile("^(.+)\\.kt$"), true);
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/cast"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
@@ -1185,6 +1185,84 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/cast/WhenWithExpression.kt");
|
doTest("compiler/testData/diagnostics/tests/cast/WhenWithExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/tests/cast/bare")
|
||||||
|
public static class Bare extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
|
public void testAllFilesPresentInBare() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/cast/bare"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AsNestedBare.kt")
|
||||||
|
public void testAsNestedBare() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/AsNestedBare.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AsNullable.kt")
|
||||||
|
public void testAsNullable() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/AsNullable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EitherAs.kt")
|
||||||
|
public void testEitherAs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/EitherAs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EitherIs.kt")
|
||||||
|
public void testEitherIs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/EitherIs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EitherNotIs.kt")
|
||||||
|
public void testEitherNotIs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/EitherNotIs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EitherSafeAs.kt")
|
||||||
|
public void testEitherSafeAs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/EitherSafeAs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("EitherWhen.kt")
|
||||||
|
public void testEitherWhen() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/EitherWhen.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ErrorsInSubstitution.kt")
|
||||||
|
public void testErrorsInSubstitution() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/ErrorsInSubstitution.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NullableAs.kt")
|
||||||
|
public void testNullableAs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/NullableAs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("RedundantNullable.kt")
|
||||||
|
public void testRedundantNullable() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/RedundantNullable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ToErrorType.kt")
|
||||||
|
public void testToErrorType() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/ToErrorType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnrelatedAs.kt")
|
||||||
|
public void testUnrelatedAs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/UnrelatedAs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnrelatedColon.kt")
|
||||||
|
public void testUnrelatedColon() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/UnrelatedColon.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("UnrelatedIs.kt")
|
||||||
|
public void testUnrelatedIs() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/cast/bare/UnrelatedIs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/cast/neverSucceeds")
|
@TestMetadata("compiler/testData/diagnostics/tests/cast/neverSucceeds")
|
||||||
public static class NeverSucceeds extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class NeverSucceeds extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInNeverSucceeds() throws Exception {
|
public void testAllFilesPresentInNeverSucceeds() throws Exception {
|
||||||
@@ -1216,6 +1294,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
public static Test innerSuite() {
|
public static Test innerSuite() {
|
||||||
TestSuite suite = new TestSuite("Cast");
|
TestSuite suite = new TestSuite("Cast");
|
||||||
suite.addTestSuite(Cast.class);
|
suite.addTestSuite(Cast.class);
|
||||||
|
suite.addTestSuite(Bare.class);
|
||||||
suite.addTestSuite(NeverSucceeds.class);
|
suite.addTestSuite(NeverSucceeds.class);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user