From ae854b1e38f60ef48a1726699b17c5df7ed33e5f Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 26 Jan 2011 22:38:52 +0300 Subject: [PATCH] Subtyping works for parameterized superclasses --- .../jetbrains/jet/lang/types/ErrorType.java | 2 +- .../jet/lang/types/JetTypeChecker.java | 23 +++++++++++-- .../jet/lang/types/NullableType.java | 33 +++++++++++++++++++ .../jet/lang/types/TypeVariable.java | 7 ++++ .../jetbrains/jet/lang/types/TypeVisitor.java | 4 +++ .../jet/types/JetTypeCheckerTest.java | 7 ++-- 6 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/types/NullableType.java diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java index 83ae2f762d6..7af0c20e08c 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -35,7 +35,7 @@ public class ErrorType extends VisitableTypeImpl implements Type { @Override public R accept(TypeVisitor visitor, D data) { - throw new UnsupportedOperationException("Not found: " + debugLabel); // TODO + return visitor.visitErrorType(this, data); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index ccfe80570a6..03c715fe47d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -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 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 newArguments = new ArrayList(); 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 newArguments) { - // TODO - return type; + return type.accept(new TypeVisitor>() { + @Override + public Type visitClassType(ClassType classType, List newArguments) { + return new ClassType(classType.getAttributes(), classType.getClassDescriptor(), newArguments); + } + + }, newArguments); } private boolean checkSubtypeForTheSameConstructor(Type subtype, Type supertype) { diff --git a/idea/src/org/jetbrains/jet/lang/types/NullableType.java b/idea/src/org/jetbrains/jet/lang/types/NullableType.java new file mode 100644 index 00000000000..7a4bb27c8ac --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/NullableType.java @@ -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 attributes) { + super(attributes); + } + + @Override + public TypeConstructor getConstructor() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public List getArguments() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public Collection getMembers() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public R accept(TypeVisitor visitor, D data) { + return visitor.visitNullableType(this, data); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java b/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java index 57af307a210..528a9e45fae 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeVariable.java @@ -12,8 +12,15 @@ import java.util.List; */ public class TypeVariable extends TypeImpl { + private final TypeParameterDescriptor typeParameterDescriptor; + public TypeVariable(@NotNull List attributes, @NotNull TypeParameterDescriptor typeParameter) { super(attributes, typeParameter.getTypeConstructor(), Collections.emptyList()); + this.typeParameterDescriptor = typeParameter; + } + + public TypeParameterDescriptor getTypeParameterDescriptor() { + return typeParameterDescriptor; } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java b/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java index 4fb07e17766..bf6f59ab705 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeVisitor.java @@ -28,6 +28,10 @@ public class TypeVisitor { 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 } diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 70d7adce87d..7b949248561 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -158,9 +158,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertNotSubtype("Base_T", "Base_T"); assertNotSubtype("Base_T<*>", "Base_T"); - assertNotSubtype("Derived_T", "Base_T"); - assertSubtype("Derived_outT", "Base_outT"); + assertSubtype("Derived_T", "Base_T"); + assertSubtype("Derived_outT", "Base_outT"); + assertSubtype("Derived_inT", "Base_inT"); + assertNotSubtype("Derived_T", "Base_T"); + assertSubtype("Derived_outT", "Base_outT"); assertSubtype("Derived_T", "Base_T"); assertSubtype("Derived_T", "Base_T");