Subtyping works for parameterized superclasses

This commit is contained in:
Andrey Breslav
2011-01-26 22:38:52 +03:00
parent 798510b719
commit ae854b1e38
6 changed files with 70 additions and 6 deletions
@@ -35,7 +35,7 @@ public class ErrorType extends VisitableTypeImpl implements Type {
@Override
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
return visitor.visitErrorType(this, data);
}
@Override
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.*;
@@ -63,7 +64,7 @@ public class JetTypeChecker {
}
public boolean isConvertibleTo(JetExpression expression, Type type) {
return false; //To change body of created methods use File | Settings | File Templates.
throw new UnsupportedOperationException(); // TODO
}
public boolean isSubtypeOf(Type subtype, Type supertype) {
@@ -107,7 +108,18 @@ public class JetTypeChecker {
return substitute(parameterValues, subject);
}
@NotNull
private Type substitute(Map<TypeParameterDescriptor, TypeProjection> parameterValues, Type subject) {
if (subject instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) subject;
TypeProjection value = parameterValues.get(typeVariable.getTypeParameterDescriptor());
if (value == null) {
return typeVariable;
}
Type type = value.getType();
assert type != null;
return type;
}
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
for (TypeProjection argument : subject.getArguments()) {
newArguments.add(new TypeProjection(argument.getProjectionKind(), substitute(parameterValues, argument.getType())));
@@ -116,8 +128,13 @@ public class JetTypeChecker {
}
private Type specializeType(Type type, List<TypeProjection> newArguments) {
// TODO
return type;
return type.accept(new TypeVisitor<Type, List<TypeProjection>>() {
@Override
public Type visitClassType(ClassType classType, List<TypeProjection> newArguments) {
return new ClassType(classType.getAttributes(), classType.getClassDescriptor(), newArguments);
}
}, newArguments);
}
private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) {
@@ -0,0 +1,33 @@
package org.jetbrains.jet.lang.types;
import java.util.Collection;
import java.util.List;
/**
* @author abreslav
*/
public class NullableType extends VisitableTypeImpl {
public NullableType(List<Attribute> attributes) {
super(attributes);
}
@Override
public TypeConstructor getConstructor() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public List<TypeProjection> getArguments() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public Collection<MemberDescriptor> getMembers() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
return visitor.visitNullableType(this, data);
}
}
@@ -12,8 +12,15 @@ import java.util.List;
*/
public class TypeVariable extends TypeImpl {
private final TypeParameterDescriptor typeParameterDescriptor;
public TypeVariable(@NotNull List<Attribute> attributes, @NotNull TypeParameterDescriptor typeParameter) {
super(attributes, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
this.typeParameterDescriptor = typeParameter;
}
public TypeParameterDescriptor getTypeParameterDescriptor() {
return typeParameterDescriptor;
}
@Override
@@ -28,6 +28,10 @@ public class TypeVisitor<R, D> {
return visitType(errorType, data);
}
public R visitNullableType(NullableType nullableType, D data) {
return visitType(nullableType, data);
}
public R visitType(Type type, D data) {
throw new UnsupportedOperationException(); // TODO
}
@@ -158,9 +158,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertNotSubtype("Base_T<in Int>", "Base_T<out Int>");
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
assertNotSubtype("Derived_T<Any>", "Base_T<Any>");
assertSubtype("Derived_outT<Any>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<Int>");
assertSubtype("Derived_outT<Int>", "Base_outT<Int>");
assertSubtype("Derived_inT<Int>", "Base_inT<Int>");
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
assertSubtype("Derived_T<Any>", "Base_T<in Int>");