Subtyping works for parameterized superclasses
This commit is contained in:
@@ -35,7 +35,7 @@ public class ErrorType extends VisitableTypeImpl implements Type {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(TypeVisitor<R, D> visitor, D data) {
|
||||||
throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO
|
return visitor.visitErrorType(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.jet.lang.types;
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
|
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;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -63,7 +64,7 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConvertibleTo(JetExpression expression, Type type) {
|
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) {
|
public boolean isSubtypeOf(Type subtype, Type supertype) {
|
||||||
@@ -107,7 +108,18 @@ public class JetTypeChecker {
|
|||||||
return substitute(parameterValues, subject);
|
return substitute(parameterValues, subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private Type substitute(Map<TypeParameterDescriptor, TypeProjection> parameterValues, Type subject) {
|
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>();
|
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
|
||||||
for (TypeProjection argument : subject.getArguments()) {
|
for (TypeProjection argument : subject.getArguments()) {
|
||||||
newArguments.add(new TypeProjection(argument.getProjectionKind(), substitute(parameterValues, argument.getType())));
|
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) {
|
private Type specializeType(Type type, List<TypeProjection> newArguments) {
|
||||||
// TODO
|
return type.accept(new TypeVisitor<Type, List<TypeProjection>>() {
|
||||||
return type;
|
@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) {
|
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 {
|
public class TypeVariable extends TypeImpl {
|
||||||
|
|
||||||
|
private final TypeParameterDescriptor typeParameterDescriptor;
|
||||||
|
|
||||||
public TypeVariable(@NotNull List<Attribute> attributes, @NotNull TypeParameterDescriptor typeParameter) {
|
public TypeVariable(@NotNull List<Attribute> attributes, @NotNull TypeParameterDescriptor typeParameter) {
|
||||||
super(attributes, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
|
super(attributes, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
|
||||||
|
this.typeParameterDescriptor = typeParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeParameterDescriptor getTypeParameterDescriptor() {
|
||||||
|
return typeParameterDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ public class TypeVisitor<R, D> {
|
|||||||
return visitType(errorType, data);
|
return visitType(errorType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public R visitNullableType(NullableType nullableType, D data) {
|
||||||
|
return visitType(nullableType, data);
|
||||||
|
}
|
||||||
|
|
||||||
public R visitType(Type type, D data) {
|
public R visitType(Type type, D data) {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
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<in Int>", "Base_T<out Int>");
|
||||||
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
|
assertNotSubtype("Base_T<*>", "Base_T<out Int>");
|
||||||
|
|
||||||
assertNotSubtype("Derived_T<Any>", "Base_T<Any>");
|
assertSubtype("Derived_T<Int>", "Base_T<Int>");
|
||||||
assertSubtype("Derived_outT<Any>", "Base_outT<Any>");
|
assertSubtype("Derived_outT<Int>", "Base_outT<Int>");
|
||||||
|
assertSubtype("Derived_inT<Int>", "Base_inT<Int>");
|
||||||
|
|
||||||
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
|
assertNotSubtype("Derived_T<Int>", "Base_T<Any>");
|
||||||
|
|
||||||
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
|
assertSubtype("Derived_outT<Int>", "Base_outT<Any>");
|
||||||
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
|
assertSubtype("Derived_T<Int>", "Base_T<out Any>");
|
||||||
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
|
assertSubtype("Derived_T<Any>", "Base_T<in Int>");
|
||||||
|
|||||||
Reference in New Issue
Block a user