From 6770f309ac148ef7cca05a7251a81b1dc5021d45 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 13 May 2011 18:42:05 +0200 Subject: [PATCH 1/2] 'is' works for type parameters --- .../jetbrains/jet/codegen/ClassCodegen.java | 9 +--- .../jet/codegen/ExpressionCodegen.java | 42 ++++++++++++++++--- .../typeInfo/isWithGenericParameters.jet | 8 ++++ .../jetbrains/jet/codegen/TypeInfoTest.java | 6 +++ stdlib/src/jet/typeinfo/TypeInfo.java | 4 ++ 5 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 idea/testData/codegen/typeInfo/isWithGenericParameters.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index f962710f5d8..4508ca0a291 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -425,14 +425,7 @@ public class ClassCodegen { null); mv.visitCode(); InstructionAdapter v = new InstructionAdapter(mv); - String owner = JetTypeMapper.jvmNameForImplementation(descriptor); - if (descriptor.getTypeConstructor().getParameters().size() > 0) { - v.load(0, JetTypeMapper.TYPE_OBJECT); - v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - } - else { - v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - } + ExpressionCodegen.loadTypeInfo(descriptor, v); v.areturn(JetTypeMapper.TYPE_TYPEINFO); mv.visitMaxs(0, 0); mv.visitEnd(); diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 4767cf6d25d..5a08b679067 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -76,6 +76,17 @@ public class ExpressionCodegen extends JetVisitor { this.bindingContext = bindingContext; } + static void loadTypeInfo(ClassDescriptor descriptor, InstructionAdapter v) { + String owner = JetTypeMapper.jvmNameForImplementation(descriptor); + if (descriptor.getTypeConstructor().getParameters().size() > 0) { + v.load(0, JetTypeMapper.TYPE_OBJECT); + v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + else { + v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + } + } + private void gen(JetElement expr) { if (expr == null) throw new CompilationException(); expr.accept(this); @@ -1301,7 +1312,7 @@ public class ExpressionCodegen extends JetVisitor { throw new UnsupportedOperationException("don't know how to handle non-class types in is"); } if (jetType.getArguments().size() > 0) { - newTypeInfo(jetType); + generateTypeInfo(jetType); gen(expression.getLeftHandSide(), OBJECT_TYPE); v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z"); } @@ -1314,11 +1325,23 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(expression.isNot() ? StackValue.not(value) : value); } - private void newTypeInfo(JetType jetType) { + private void generateTypeInfo(JetType jetType) { + DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor instanceof TypeParameterDescriptor) { + DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration(); + if (containingDeclaration == contextType && contextType instanceof ClassDescriptor) { + int index = indexOfTypeParameter((ClassDescriptor) contextType, (TypeParameterDescriptor) declarationDescriptor); + loadTypeInfo((ClassDescriptor) contextType, v); + v.iconst(index); + v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;"); + return; + } + throw new UnsupportedOperationException("don't know what this type parameter resolves to"); + } + v.anew(JetTypeMapper.TYPE_TYPEINFO); v.dup(); - - v.aconst(typeMapper.jvmType((ClassDescriptor) jetType.getConstructor().getDeclarationDescriptor(), OwnerKind.INTERFACE)); + v.aconst(typeMapper.jvmType((ClassDescriptor) declarationDescriptor, OwnerKind.INTERFACE)); List arguments = jetType.getArguments(); if (arguments.size() > 0) { v.iconst(arguments.size()); @@ -1328,7 +1351,7 @@ public class ExpressionCodegen extends JetVisitor { TypeProjection argument = arguments.get(i); v.dup(); v.iconst(i); - newTypeInfo(argument.getType()); + generateTypeInfo(argument.getType()); v.astore(JetTypeMapper.TYPE_OBJECT); } v.invokespecial("jet/typeinfo/TypeInfo", "", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V"); @@ -1338,6 +1361,15 @@ public class ExpressionCodegen extends JetVisitor { } } + private int indexOfTypeParameter(ClassDescriptor classDescriptor, TypeParameterDescriptor typeParameterDescriptor) { + List parameters = classDescriptor.getTypeConstructor().getParameters(); + int index = parameters.indexOf(typeParameterDescriptor); + if (index < 0) { + throw new UnsupportedOperationException("can't find type parameter index"); + } + return index; + } + private static class CompilationException extends RuntimeException { } } diff --git a/idea/testData/codegen/typeInfo/isWithGenericParameters.jet b/idea/testData/codegen/typeInfo/isWithGenericParameters.jet new file mode 100644 index 00000000000..d0bdd851ffc --- /dev/null +++ b/idea/testData/codegen/typeInfo/isWithGenericParameters.jet @@ -0,0 +1,8 @@ +class Wrapper() { + fun isSameWrapper(wrapper: Any) = wrapper is Wrapper +} + +fun foo() { + val wrapper = new Wrapper() + return wrapper.isSameWrapper(new Wrapper()) +} diff --git a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 998704da068..800973cf507 100644 --- a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -59,6 +59,12 @@ public class TypeInfoTest extends CodegenTestCase { assertFalse((Boolean) foo.invoke(null, newRunnable())); } + public void testIsWithGenericParameters() throws Exception { + loadFile(); + Method foo = generateFunction(); + assertFalse((Boolean) foo.invoke(null)); + } + private Runnable newRunnable() { return new Runnable() { @Override diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 5f80f501fe2..e29ec82bc22 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -47,6 +47,10 @@ public class TypeInfo implements JetObject { return true; } + public TypeInfo getTypeParameter(int index) { + return typeParameters[index]; + } + @Override public TypeInfo getTypeInfo() { if (typeInfo == null) { From 797f9fcc562dc11cc3e450b2f52ee36b2057a384 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 13 May 2011 20:53:36 +0400 Subject: [PATCH 2/2] Indices for type parameters --- .../descriptors/TypeParameterDescriptor.java | 19 ++++++++++++++----- .../lang/resolve/ClassDescriptorResolver.java | 15 ++++++++++----- .../resolve/java/JavaDescriptorResolver.java | 3 ++- .../jet/lang/types/JetStandardClasses.java | 8 ++++---- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/idea/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index a8f44435358..7e2d540afb1 100644 --- a/idea/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -16,8 +16,9 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Variance variance, - @NotNull String name) { - TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, variance, name); + @NotNull String name, + int index) { + TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, variance, name, index); typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound()); return typeParameterDescriptor; } @@ -26,10 +27,12 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Variance variance, - @NotNull String name) { - return new TypeParameterDescriptor(containingDeclaration, annotations, variance, name); + @NotNull String name, + int index) { + return new TypeParameterDescriptor(containingDeclaration, annotations, variance, name, index); } + private final int index; private final Variance variance; private final Set upperBounds; private final TypeConstructor typeConstructor; @@ -40,8 +43,10 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull Variance variance, - @NotNull String name) { + @NotNull String name, + int index) { super(containingDeclaration, annotations, name); + this.index = index; this.variance = variance; this.upperBounds = Sets.newLinkedHashSet(); // TODO: Should we actually pass the annotations on to the type constructor? @@ -114,4 +119,8 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement } return type; } + + public int getIndex() { + return index; + } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 8bba26ff21b..5094d47cebe 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -84,16 +84,19 @@ public class ClassDescriptorResolver { // TODO : Where-clause List typeParameters = Lists.newArrayList(); + int index = 0; for (JetTypeParameter typeParameter : classElement.getTypeParameters()) { TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( descriptor, AnnotationResolver.INSTANCE.resolveAnnotations(typeParameter.getModifierList()), typeParameter.getVariance(), - JetPsiUtil.safeName(typeParameter.getName()) + JetPsiUtil.safeName(typeParameter.getName()), + index ); parameterScope.addTypeParameterDescriptor(typeParameterDescriptor); trace.recordDeclarationResolution(typeParameter, typeParameterDescriptor); typeParameters.add(typeParameterDescriptor); + index++; } boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD); @@ -301,13 +304,14 @@ public class ClassDescriptorResolver { public List resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List typeParameters) { // TODO : Where-clause List result = new ArrayList(); - for (JetTypeParameter typeParameter : typeParameters) { - result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter)); + for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { + JetTypeParameter typeParameter = typeParameters.get(i); + result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter, i)); } return result; } - private TypeParameterDescriptor resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter) { + private TypeParameterDescriptor resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index) { // TODO: other bounds from where-clause JetTypeReference extendsBound = typeParameter.getExtendsBound(); JetType bound = extendsBound == null @@ -317,7 +321,8 @@ public class ClassDescriptorResolver { containingDescriptor, AnnotationResolver.INSTANCE.resolveAnnotations(typeParameter.getModifierList()), typeParameter.getVariance(), - JetPsiUtil.safeName(typeParameter.getName()) + JetPsiUtil.safeName(typeParameter.getName()), + index ); typeParameterDescriptor.addUpperBound(bound); extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 0e3f4838546..f6867545944 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -125,7 +125,8 @@ public class JavaDescriptorResolver { owner, Collections.emptyList(), // TODO Variance.INVARIANT, - typeParameter.getName() + typeParameter.getName(), + typeParameter.getIndex() ); PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes(); if (referencedTypes.length == 0){ diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index 7e9bcff771e..ae9bb84ce80 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -102,7 +102,7 @@ public class JetStandardClasses { parameters.add(TypeParameterDescriptor.createWithDefaultBound( classDescriptor, Collections.emptyList(), - Variance.OUT_VARIANCE, "T" + j)); + Variance.OUT_VARIANCE, "T" + j, j)); } TUPLE[i] = classDescriptor.initialize( true, @@ -140,7 +140,7 @@ public class JetStandardClasses { parameters.add(0, TypeParameterDescriptor.createWithDefaultBound( receiverFunction, Collections.emptyList(), - Variance.IN_VARIANCE, "T")); + Variance.IN_VARIANCE, "T", 0)); RECEIVER_FUNCTION[i] = receiverFunction.initialize( false, parameters, @@ -154,12 +154,12 @@ public class JetStandardClasses { parameters.add(TypeParameterDescriptor.createWithDefaultBound( function, Collections.emptyList(), - Variance.IN_VARIANCE, "P" + j)); + Variance.IN_VARIANCE, "P" + j, j + 1)); } parameters.add(TypeParameterDescriptor.createWithDefaultBound( function, Collections.emptyList(), - Variance.OUT_VARIANCE, "R")); + Variance.OUT_VARIANCE, "R", parameterCount + 1)); return parameters; }