From 990bd7e71dc0cf2e2c97f5ab6b4eea5fca93e91d Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 3 Nov 2015 14:12:36 +0300 Subject: [PATCH] Correct parameters of inner's class type constructor Now it contains copies of outer's class constructor parameters They are appended just after real type parameters --- .../kotlin/codegen/state/JetTypeMapper.java | 2 + .../lazy/descriptors/LazyClassDescriptor.java | 2 +- .../descriptors/LazyJavaClassDescriptor.kt | 2 +- .../descriptors/TypeParameterDescriptor.java | 11 +++++ .../impl/AbstractTypeParameterDescriptor.java | 5 ++ .../impl/LazySubstitutingClassDescriptor.java | 12 ++++- .../kotlin/descriptors/typeParameterUtils.kt | 46 +++++++++++++++++++ .../kotlin/types/TypeConstructor.java | 6 +++ .../DeserializedClassDescriptor.kt | 6 ++- 9 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 core/descriptors/src/org/jetbrains/kotlin/descriptors/typeParameterUtils.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java index f8911386388..0c5fd1545f3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/JetTypeMapper.java @@ -642,6 +642,8 @@ public class JetTypeMapper { List arguments = jetType.getArguments(); for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) { + if (parameter.isCopyFromOuterDeclaration()) continue; + TypeProjection argument = arguments.get(parameter.getIndex()); if (projectionsAllowed && argument.isStarProjection()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index ba836e5a5e5..51ca9931daa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -576,7 +576,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes private final NotNullLazyValue> parameters = c.getStorageManager().createLazyValue(new Function0>() { @Override public List invoke() { - return LazyClassDescriptor.this.getDeclaredTypeParameters(); + return TypeParameterUtilsKt.computeConstructorTypeParameters(LazyClassDescriptor.this); } }); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 3d5df28148a..51230ff1149 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -131,7 +131,7 @@ class LazyJavaClassDescriptor( private inner class LazyJavaClassTypeConstructor : AbstractClassTypeConstructor() { private val parameters = c.storageManager.createLazyValue { - this@LazyJavaClassDescriptor.declaredTypeParameters + this@LazyJavaClassDescriptor.computeConstructorTypeParameters() } override fun getParameters(): List = parameters() diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java index 28b4fea57b7..03f1375dd7b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java @@ -46,4 +46,15 @@ public interface TypeParameterDescriptor extends ClassifierDescriptor { TypeParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor); int getIndex(); + + /** + * Is current parameter just a copy of another type parameter (getOriginal) from outer declaration + * to be used for type constructor of inner declaration (i.e. inner class). + * + * If this method returns true: + * 1. Containing declaration for current parameter is the inner one + * 2. 'getOriginal' returns original type parameter from outer declaration + * 3. 'getTypeConstructor' is the same as for original declaration (at least in means of 'equals') + */ + boolean isCapturedFromOuterDeclaration(); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java index 5a7c1a3b515..355433135cb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -166,6 +166,11 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip return index; } + @Override + public boolean isCapturedFromOuterDeclaration() { + return false; + } + @NotNull @Override public List getUpperBounds() { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java index 61b0fcb5bd0..25f8ee43ba4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/LazySubstitutingClassDescriptor.java @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.descriptors.impl; +import kotlin.CollectionsKt; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; @@ -34,6 +36,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { private final TypeSubstitutor originalSubstitutor; private TypeSubstitutor newSubstitutor; private List typeConstructorParameters; + private List declaredTypeParameters; private TypeConstructor typeConstructor; public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, TypeSubstitutor substitutor) { @@ -52,6 +55,13 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { newSubstitutor = DescriptorSubstitutor.substituteTypeParameters( originalTypeParameters, originalSubstitutor.getSubstitution(), this, typeConstructorParameters ); + + declaredTypeParameters = CollectionsKt.filter(typeConstructorParameters, new Function1() { + @Override + public Boolean invoke(TypeParameterDescriptor descriptor) { + return !descriptor.isCapturedFromOuterDeclaration(); + } + }); } } return newSubstitutor; @@ -253,6 +263,6 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { @Override public List getDeclaredTypeParameters() { getSubstitutor(); - return typeConstructorParameters; + return declaredTypeParameters; } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/typeParameterUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/typeParameterUtils.kt new file mode 100644 index 00000000000..788d6316378 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/typeParameterUtils.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.descriptors + +fun ClassDescriptor.computeConstructorTypeParameters(): List { + val declaredParameters = declaredTypeParameters + + if (!isInner) return declaredParameters + val containingTypeConstructor = (containingDeclaration as? ClassDescriptor)?.typeConstructor ?: return emptyList() + + val additional = containingTypeConstructor.parameters.map { it.capturedCopyForInnerDeclaration(this, declaredParameters.size) } + if (additional.isEmpty()) return declaredParameters + + return declaredParameters + additional +} + +private fun TypeParameterDescriptor.capturedCopyForInnerDeclaration( + declarationDescriptor: DeclarationDescriptor, + declaredTypeParametersCount: Int +) = CapturedTypeParameterDescriptor(this, declarationDescriptor, declaredTypeParametersCount) + +private class CapturedTypeParameterDescriptor( + private val originalDescriptor: TypeParameterDescriptor, + private val declarationDescriptor: DeclarationDescriptor, + private val declaredTypeParametersCount: Int +) : TypeParameterDescriptor by originalDescriptor { + override fun isCapturedFromOuterDeclaration() = true + override fun getOriginal() = originalDescriptor.original + override fun getContainingDeclaration() = declarationDescriptor + override fun getIndex() = declaredTypeParametersCount + originalDescriptor.index + override fun toString() = originalDescriptor.toString() + "[inner-copy]" +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java index 38bd4c130f8..b27186c5b1b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructor.java @@ -28,6 +28,12 @@ import java.util.Collection; import java.util.List; public interface TypeConstructor extends Annotated { + /** + * It may differ from ClassDescriptor.declaredParameters if the class is inner, in such case + * it also contains additional parameters from outer declarations. + * + * @return list of parameters for type constructor, both from current declaration and the outer one + */ @NotNull @ReadOnly List getParameters(); diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt index d550d0b1cfd..965ee83adfd 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedClassDescriptor.kt @@ -173,7 +173,11 @@ public class DeserializedClassDescriptor( computeSupertypes() } - override fun getParameters() = c.typeDeserializer.ownTypeParameters + private val parameters = c.storageManager.createLazyValue { + this@DeserializedClassDescriptor.computeConstructorTypeParameters() + } + + override fun getParameters() = parameters() override fun getSupertypes() = supertypes()