Use "Any?" as out-type for type parameters instead of intersection of bounds

Also refactor checkSubtypeForTheSameConstructor to compute everything in the
best order
This commit is contained in:
Alexander Udalov
2015-10-22 23:26:37 +03:00
parent bed75e8af2
commit 12d6b6e7e4
4 changed files with 93 additions and 20 deletions
@@ -0,0 +1,18 @@
import java.io.Serializable
class A<T> where T : Cloneable, T : Serializable
interface CS1 : Cloneable, Serializable
interface CS2 : CS1
interface I1 {
fun foo(): A<in CS2>
}
interface I2 : I1 {
override fun foo(): A<CS1>
}
interface I3 : I1 {
override fun foo(): A<in CS1>
}
@@ -0,0 +1,43 @@
package
public final class A</*0*/ T : kotlin.Cloneable> where T : java.io.Serializable {
public constructor A</*0*/ T : kotlin.Cloneable>() where T : java.io.Serializable
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface CS1 : kotlin.Cloneable, java.io.Serializable {
protected open override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface CS2 : CS1 {
protected open override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I1 {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(): A<in CS2>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I2 : I1 {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ fun foo(): A<CS1>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I3 : I1 {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ fun foo(): A<in CS1>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -15657,6 +15657,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("invariantArgumentForTypeParameterWithMultipleBounds.kt")
public void testInvariantArgumentForTypeParameterWithMultipleBounds() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/subtyping/invariantArgumentForTypeParameterWithMultipleBounds.kt");
doTest(fileName);
}
@TestMetadata("kt2069.kt")
public void testKt2069() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/subtyping/kt2069.kt");
@@ -20,9 +20,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.kotlin.types.Variance.*;
@@ -43,12 +46,14 @@ public class TypeCheckingProcedure {
return UtilsKt.findCorrespondingSupertype(subtype, supertype, typeCheckingProcedureCallbacks);
}
public static KotlinType getOutType(TypeParameterDescriptor parameter, TypeProjection argument) {
boolean isOutProjected = argument.getProjectionKind() == IN_VARIANCE || parameter.getVariance() == IN_VARIANCE;
return isOutProjected ? parameter.getUpperBoundsAsType() : argument.getType();
@NotNull
private static KotlinType getOutType(@NotNull TypeParameterDescriptor parameter, @NotNull TypeProjection argument) {
boolean isInProjected = argument.getProjectionKind() == IN_VARIANCE || parameter.getVariance() == IN_VARIANCE;
return isInProjected ? DescriptorUtilsKt.getBuiltIns(parameter).getNullableAnyType() : argument.getType();
}
public static KotlinType getInType(@NotNull TypeParameterDescriptor parameter, @NotNull TypeProjection argument) {
@NotNull
private static KotlinType getInType(@NotNull TypeParameterDescriptor parameter, @NotNull TypeProjection argument) {
boolean isOutProjected = argument.getProjectionKind() == OUT_VARIANCE || parameter.getVariance() == OUT_VARIANCE;
return isOutProjected ? DescriptorUtilsKt.getBuiltIns(parameter).getNothingType() : argument.getType();
}
@@ -229,30 +234,31 @@ public class TypeCheckingProcedure {
TypeParameterDescriptor parameter = parameters.get(i);
TypeProjection superArgument = superArguments.get(i);
if (superArgument.isStarProjection()) continue;
KotlinType superIn = getInType(parameter, superArgument);
KotlinType superOut = getOutType(parameter, superArgument);
TypeProjection subArgument = subArguments.get(i);
KotlinType subIn = getInType(parameter, subArgument);
KotlinType subOut = getOutType(parameter, subArgument);
if (superArgument.isStarProjection()) continue;
if (capture(subArgument, superArgument, parameter)) continue;
boolean argumentIsErrorType = subArgument.getType().isError() || superArgument.getType().isError();
if (!argumentIsErrorType && parameter.getVariance() == INVARIANT
&& subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) {
if (!argumentIsErrorType && parameter.getVariance() == INVARIANT &&
subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) {
if (!constraints.assertEqualTypes(subArgument.getType(), superArgument.getType(), this)) return false;
continue;
}
KotlinType superOut = getOutType(parameter, superArgument);
KotlinType subOut = getOutType(parameter, subArgument);
if (!constraints.assertSubtype(subOut, superOut, this)) return false;
KotlinType superIn = getInType(parameter, superArgument);
KotlinType subIn = getInType(parameter, subArgument);
if (superArgument.getProjectionKind() != Variance.OUT_VARIANCE) {
if (!constraints.assertSubtype(superIn, subIn, this)) return false;
}
else {
if (!constraints.assertSubtype(subOut, superOut, this)) return false;
if (superArgument.getProjectionKind() != Variance.OUT_VARIANCE) {
if (!constraints.assertSubtype(superIn, subIn, this)) return false;
}
else {
assert KotlinBuiltIns.isNothing(superIn) : "In component must be Nothing for out-projection";
}
assert KotlinBuiltIns.isNothing(superIn) : "In component must be Nothing for out-projection";
}
}
return true;