Subtyping for type constructor applications with projections

This commit is contained in:
Andrey Breslav
2011-01-25 18:54:26 +03:00
parent 0d63670175
commit 308ab1c4eb
6 changed files with 117 additions and 15 deletions
@@ -28,7 +28,6 @@ public class JetStandardClasses {
private static final ClassDescriptor DOUBLE = new ClassDescriptor("Double");
private static final ClassDescriptor BOOLEAN = new ClassDescriptor("Boolean");
private static final ClassDescriptor STRING = new ClassDescriptor("String");
private static final ClassDescriptor UNIT = new ClassDescriptor("Unit");
public static final int TUPLE_COUNT = 22;
private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT];
@@ -110,7 +110,7 @@ public class JetTypeChecker {
private Type substitute(Map<TypeParameterDescriptor, TypeProjection> parameterValues, Type subject) {
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
for (TypeProjection argument : subject.getArguments()) {
newArguments.add(new TypeProjection(argument.getProjection(), substitute(parameterValues, argument.getType())));
newArguments.add(new TypeProjection(argument.getProjectionKind(), substitute(parameterValues, argument.getType())));
}
return specializeType(subject, newArguments);
}
@@ -121,10 +121,82 @@ public class JetTypeChecker {
}
private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) {
assert subtype.getConstructor().equals(supertype.getConstructor());
TypeConstructor constructor = subtype.getConstructor();
assert constructor.equals(supertype.getConstructor());
List<TypeProjection> subArguments = subtype.getArguments();
List<TypeProjection> superArguments = supertype.getArguments();
List<TypeParameterDescriptor> parameters = constructor.getParameters();
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
TypeProjection subArgument = subArguments.get(i);
TypeProjection superArgument = superArguments.get(i);
Type subArgumentType = subArgument.getType();
Type superArgumentType = superArgument.getType();
switch (parameter.getVariance()) {
case INVARIANT:
switch (superArgument.getProjectionKind()) {
case NO_PROJECTION:
if (!subArgumentType.equals(superArgumentType)) {
return false;
}
break;
case NEITHER_OUT_NOR_IN:
if (!isSubtypeOf(subArgumentType, superArgumentType)) {
return false;
}
break;
case OUT_ONLY:
if (subArgument.getProjectionKind() != ProjectionKind.OUT_ONLY) {
return false;
}
if (!isSubtypeOf(subArgumentType, superArgumentType)) {
return false;
}
break;
case IN_ONLY:
if (subArgument.getProjectionKind() != ProjectionKind.IN_ONLY) {
return false;
}
if (!isSubtypeOf(superArgumentType, subArgumentType)) {
return false;
}
break;
}
break;
case IN_VARIANCE:
switch (superArgument.getProjectionKind()) {
case NO_PROJECTION:
case IN_ONLY:
if (!isSubtypeOf(superArgumentType, subArgumentType)) {
return false;
}
break;
case NEITHER_OUT_NOR_IN:
case OUT_ONLY:
if (!isSubtypeOf(subArgumentType, superArgumentType)) {
return false;
}
break;
}
break;
case OUT_VARIANCE:
switch (superArgument.getProjectionKind()) {
case NO_PROJECTION:
case OUT_ONLY:
case NEITHER_OUT_NOR_IN:
case IN_ONLY:
if (!isSubtypeOf(subArgumentType, superArgumentType)) {
return false;
}
break;
}
break;
}
}
// TODO
return true;
}
}
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public enum ProjectionKind {
OUT_ONLY("out"),
IN_ONLY("in"),
NEITHER_OUT_NOR_IN("*"),
NO_PROJECTION("");
private final String text;
ProjectionKind(String text) {
this.text = text;
}
@Override
public String toString() {
return text;
}
}
@@ -51,7 +51,7 @@ public class TupleType extends TypeImpl {
private static List<TypeProjection> toProjections(List<Type> arguments) {
List<TypeProjection> result = new ArrayList<TypeProjection>();
for (Type argument : arguments) {
result.add(new TypeProjection(Variance.OUT_VARIANCE, argument));
result.add(new TypeProjection(ProjectionKind.OUT_ONLY, argument));
}
return result;
}
@@ -4,19 +4,19 @@ package org.jetbrains.jet.lang.types;
* @author abreslav
*/
public class TypeProjection {
private final Variance projection;
private final ProjectionKind projection;
private final Type type;
public TypeProjection(Variance projection, Type type) {
public TypeProjection(ProjectionKind projection, Type type) {
this.projection = projection;
this.type = type;
}
public TypeProjection(Type type) {
this(Variance.INVARIANT, type);
this(ProjectionKind.NO_PROJECTION, type);
}
public Variance getProjection() {
public ProjectionKind getProjectionKind() {
return projection;
}
@@ -128,6 +128,10 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertSubtype("(Double)", "(Double)");
assertSubtype("(Unit)", "(Unit)");
assertNotSubtype("(Unit)", "(Int)");
assertSubtype("(Unit)", "(Any)");
}
private void assertSubtype(String type1, String type2) {
@@ -153,10 +157,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
JetTypeElement typeElement = typeNode.getTypeElement();
List<JetTypeReference> argumentElements = typeNode.getTypeArguments();
final List<Type> arguments = new ArrayList<Type>();
for (JetTypeReference argumentElement : argumentElements) {
arguments.add(toType(argumentElement));
}
final List<Type> arguments = toTypes(argumentElements);
// TODO annotations
final Type[] result = new Type[1];
@@ -169,7 +170,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
@Override
public void visitTupleType(JetTupleType type) {
// TODO labels
result[0] = TupleType.getTupleType(arguments);
result[0] = TupleType.getTupleType(toTypes(type.getComponentTypeRefs()));
}
@Override
@@ -181,6 +182,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
return result[0];
}
private List<Type> toTypes(List<JetTypeReference> argumentElements) {
final List<Type> arguments = new ArrayList<Type>();
for (JetTypeReference argumentElement : argumentElements) {
arguments.add(toType(argumentElement));
}
return arguments;
}
public void testImplicitConversions() throws Exception {
assertConvertibleTo("1", JetStandardTypes.getByte());
}