diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt index c1a1128f01f..419ddbe7851 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt @@ -21,25 +21,27 @@ import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.utils.DFS +import org.jetbrains.kotlin.utils.SmartList class SupertypeLoopCheckerImpl : SupertypeLoopChecker { override fun findLoopsInSupertypesAndDisconnect( currentTypeConstructor: TypeConstructor, - superTypes: MutableCollection, + superTypes: Collection, neighbors: (TypeConstructor) -> Iterable, reportLoop: (KotlinType) -> Unit - ) { - + ): Collection { val graph = DFS.Neighbors { node -> neighbors(node).map { it.constructor } } - val iterator = superTypes.iterator() - while (iterator.hasNext()) { - val item = iterator.next() - if (isReachable(item.constructor, currentTypeConstructor, graph)) { - iterator.remove() - reportLoop(item) + val superTypesToRemove = SmartList() + + for (superType in superTypes) { + if (isReachable(superType.constructor, currentTypeConstructor, graph)) { + superTypesToRemove.add(superType) + reportLoop(superType) } } + + return if (superTypesToRemove.isEmpty()) superTypes else superTypes - superTypesToRemove } } 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 a251b202aac..707343554ef 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 @@ -21,11 +21,9 @@ import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNameIdentifierOwner; -import kotlin.Unit; import kotlin.collections.CollectionsKt; import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.Mutable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.ReadOnly; @@ -568,59 +566,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes return parameters.invoke(); } - private static class Supertypes { - @Mutable - public final Collection trueSupertypes; - @Mutable - public final Collection allSuperTypes; - - private Supertypes(@Mutable @NotNull Collection allSuperTypes) { - this.trueSupertypes = allSuperTypes; - this.allSuperTypes = new ArrayList(allSuperTypes); - } - - @NotNull - public Collection getAllSupertypes() { - return allSuperTypes; - } - } - private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity { - private final NotNullLazyValue supertypes = c.getStorageManager().createLazyValueWithPostCompute( - new Function0() { - @Override - public Supertypes invoke() { - if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) { - return new Supertypes(Collections.emptyList()); - } - - KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject(); - if (classOrObject == null) { - return new Supertypes(Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType())); - } - - List allSupertypes = c.getDescriptorResolver() - .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject, - c.getTrace()); - - return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE))); - } - }, - new Function1() { - @Override - public Supertypes invoke(Boolean firstTime) { - return new Supertypes(Collections.emptyList()); - } - }, - new Function1() { - @Override - public Unit invoke(@NotNull Supertypes supertypes) { - findAndDisconnectLoopsInTypeHierarchy(supertypes.trueSupertypes); - return Unit.INSTANCE; - } - } - ); - private final NotNullLazyValue> parameters = c.getStorageManager().createLazyValue(new Function0>() { @Override public List invoke() { @@ -637,40 +583,37 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } }, null); - @NotNull - @Override - public List getParameters() { - return parameters.invoke(); + public LazyClassTypeConstructor() { + super(LazyClassDescriptor.this.c.getStorageManager()); } @NotNull @Override - public Collection getSupertypes() { - return supertypes.invoke().trueSupertypes; + protected Collection computeSupertypes() { + if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) { + return Collections.emptyList(); + } + + KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject(); + if (classOrObject == null) { + return Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType()); + } + + List allSupertypes = + c.getDescriptorResolver() + .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject, + c.getTrace()); + + return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); } - private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection supertypes) { - c.getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect( - typeConstructor, supertypes, - new Function1>() { - @Override - public Iterable invoke(TypeConstructor typeConstructor) { - return getNeighbors(typeConstructor); - } - }, - new Function1() { - @Override - public Unit invoke(KotlinType type) { - ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor(); - if (supertypeDescriptor instanceof ClassDescriptor) { - ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor; - reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass); - } - - return Unit.INSTANCE; - } - } - ); + @Override + protected void reportSupertypeLoopError(@NotNull KotlinType type) { + ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor(); + if (supertypeDescriptor instanceof ClassDescriptor) { + ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor; + reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass); + } } private void reportCyclicInheritanceHierarchyError( @@ -704,22 +647,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } } - private Collection getNeighbors(TypeConstructor from) { - // Supertypes + type for container - Collection neighbours = new ArrayList( - from instanceof LazyClassTypeConstructor - ? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes() - : from.getSupertypes() - ); + @NotNull + @Override + protected SupertypeLoopChecker getSupertypeLoopChecker() { + return c.getSupertypeLoopChecker(); + } - ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor(); - if (fromDescriptor != null) { - DeclarationDescriptor container = fromDescriptor.getContainingDeclaration(); - if (container instanceof ClassDescriptor) { - neighbours.add(((ClassDescriptor) container).getDefaultType()); - } - } - return neighbours; + @NotNull + @Override + public List getParameters() { + return parameters.invoke(); } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java index 337514e7434..46a1d639c42 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java @@ -52,22 +52,16 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri typeParameter.getVariance(), typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD), index, - KotlinSourceElementKt.toSourceElement(typeParameter) - ); + KotlinSourceElementKt.toSourceElement(typeParameter), + c.getSupertypeLoopChecker()); this.c = c; this.typeParameter = typeParameter; this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this); } - @NotNull @Override - protected SupertypeLoopChecker getSupertypeLoopChecker() { - return c.getSupertypeLoopChecker(); - } - - @Override - protected void reportCycleError(@NotNull KotlinType type) { + protected void reportSupertypeLoopError(@NotNull KotlinType type) { for (KtTypeReference typeReference : getAllUpperBounds()) { if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) { c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference)); diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt index f5af25dbbd6..3d4d8052a1f 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.txt @@ -1,8 +1,6 @@ package -public/*package*/ interface A : C { - public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit - public abstract override /*1*/ /*fake_override*/ fun baz(): kotlin.Unit +public/*package*/ interface A { public abstract fun foo(): kotlin.Unit } @@ -10,7 +8,6 @@ public interface B { public abstract fun bar(): kotlin.Unit } -public/*package*/ interface C : B { - public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit +public/*package*/ interface C { public abstract fun baz(): kotlin.Unit } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.txt index eeb07f3cba1..d7daa7c7584 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.txt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.txt @@ -1,8 +1,7 @@ package -public/*package*/ open class J : K { +public/*package*/ open class J { public/*package*/ constructor J() - public final override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit public/*package*/ open fun foo(): kotlin.Unit } diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.txt index 084105179d9..3b403038632 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.txt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.txt @@ -5,10 +5,9 @@ public open class I { public final fun foo(): kotlin.Unit } -public/*package*/ open class J : I { +public/*package*/ open class J { public/*package*/ constructor J() public/*package*/ open fun bar(): kotlin.Unit - public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit } public open class K { diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.txt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.txt index ed1efcf8875..a59c286048d 100644 --- a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.txt +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaNestedCycle.txt @@ -3,9 +3,9 @@ package public interface ExceptionTracker { } -public/*package*/ open class LockBasedStorageManager : StorageManager { +public/*package*/ open class LockBasedStorageManager { public/*package*/ constructor LockBasedStorageManager() - @java.lang.Override() public/*package*/ open override /*1*/ fun foo(): kotlin.Unit + @java.lang.Override() public/*package*/ open fun foo(): kotlin.Unit public/*package*/ interface ExceptionHandlingStrategy { public abstract fun bar(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.kt b/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.kt index 15adca210d5..b63add0945b 100644 --- a/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.kt +++ b/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.kt @@ -1,7 +1,7 @@ -fun <T : F?, F : T?> foo1() {} +fun <T : F?, F : T?> foo1() {} -fun F : E, E : F?> foo2() {} +fun F : E, E : F?> foo2() {} -fun <T, F> foo3() where T : F?, F : T {} +fun <T, F> foo3() where T : F?, F : T {} -fun F, E> foo4() where T : F?, F : E, E : F? {} \ No newline at end of file +fun F, E> foo4() where T : F?, F : E, E : F? {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.txt b/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.txt index 918ffd247d3..9e5b6d38929 100644 --- a/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.txt +++ b/compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.txt @@ -1,6 +1,6 @@ package -public fun foo1(): kotlin.Unit -public fun foo2(): kotlin.Unit -public fun foo3(): kotlin.Unit -public fun foo4(): kotlin.Unit +public fun foo1(): kotlin.Unit +public fun foo2(): kotlin.Unit +public fun foo3(): kotlin.Unit +public fun foo4(): kotlin.Unit 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 d042618e88f..2fe1d1b9ffc 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 @@ -128,16 +128,15 @@ class LazyJavaClassDescriptor( override fun toString() = "lazy java class $fqName" - private inner class LazyJavaClassTypeConstructor : AbstractClassTypeConstructor() { - + private inner class LazyJavaClassTypeConstructor : AbstractClassTypeConstructor(c.storageManager) { private val parameters = c.storageManager.createLazyValue { this@LazyJavaClassDescriptor.computeConstructorTypeParameters() } override fun getParameters(): List = parameters() - private val supertypes = c.storageManager.createLazyValue> { - val javaTypes = jClass.getSupertypes() + override fun computeSupertypes(): Collection { + val javaTypes = jClass.supertypes val result = ArrayList(javaTypes.size) val incomplete = ArrayList(0) @@ -145,12 +144,12 @@ class LazyJavaClassDescriptor( for (javaType in javaTypes) { val jetType = c.typeResolver.transformJavaType(javaType, TypeUsage.SUPERTYPE.toAttributes()) - if (jetType.isError()) { + if (jetType.isError) { incomplete.add(javaType) continue } - if (jetType.getConstructor() == purelyImplementedSupertype?.getConstructor()) { + if (jetType.constructor == purelyImplementedSupertype?.constructor) { continue } @@ -162,12 +161,12 @@ class LazyJavaClassDescriptor( result.addIfNotNull(purelyImplementedSupertype) if (incomplete.isNotEmpty()) { - c.components.errorReporter.reportIncompleteHierarchy(getDeclarationDescriptor(), incomplete.map { javaType -> - (javaType as JavaClassifierType).getPresentableText() + c.components.errorReporter.reportIncompleteHierarchy(declarationDescriptor, incomplete.map { javaType -> + (javaType as JavaClassifierType).presentableText }) } - if (result.isNotEmpty()) result.toReadOnlyList() else listOf(c.module.builtIns.getAnyType()) + return if (result.isNotEmpty()) result.toReadOnlyList() else listOf(c.module.builtIns.anyType) } private fun getPurelyImplementedSupertype(): KotlinType? { @@ -179,10 +178,10 @@ class LazyJavaClassDescriptor( val classDescriptor = c.module.builtIns.getBuiltInClassByFqNameNullable(purelyImplementedFqName) ?: return null - if (classDescriptor.getTypeConstructor().getParameters().size != getParameters().size) return null + if (classDescriptor.typeConstructor.parameters.size != getTypeConstructor().parameters.size) return null - val parametersAsTypeProjections = getParameters().map { - parameter -> TypeProjectionImpl(Variance.INVARIANT, parameter.getDefaultType()) + val parametersAsTypeProjections = getTypeConstructor().parameters.map { + parameter -> TypeProjectionImpl(Variance.INVARIANT, parameter.defaultType) } return KotlinTypeImpl.create( @@ -192,17 +191,18 @@ class LazyJavaClassDescriptor( } private fun getPurelyImplementsFqNameFromAnnotation(): FqName? { - val annotation = this@LazyJavaClassDescriptor. - getAnnotations(). - findAnnotation(JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION) ?: return null + val annotation = + this@LazyJavaClassDescriptor.getAnnotations().findAnnotation(JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION) + ?: return null - val fqNameString = (annotation.getAllValueArguments().values.singleOrNull() as? StringValue)?.value ?: return null + val fqNameString = (annotation.allValueArguments.values.singleOrNull() as? StringValue)?.value ?: return null if (!isValidJavaFqName(fqNameString)) return null return FqName(fqNameString) } - override fun getSupertypes(): Collection = supertypes() + override val supertypeLoopChecker: SupertypeLoopChecker + get() = c.components.supertypeLoopChecker override fun getAnnotations() = Annotations.EMPTY diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt index cfb9603f058..0a7bfb937c7 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaTypeParameterDescriptor.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor import org.jetbrains.kotlin.load.java.components.TypeUsage import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext @@ -39,7 +40,7 @@ class LazyJavaTypeParameterDescriptor( Variance.INVARIANT, /* isReified = */ false, index, - SourceElement.NO_SOURCE + SourceElement.NO_SOURCE, c.components.supertypeLoopChecker ) { override fun resolveUpperBounds(): List { @@ -55,9 +56,7 @@ class LazyJavaTypeParameterDescriptor( } } - override fun getSupertypeLoopChecker() = c.components.supertypeLoopChecker - - override fun reportCycleError(type: KotlinType) { + override fun reportSupertypeLoopError(type: KotlinType) { // Do nothing } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassDescriptor.kt index 31da1430618..801fbc185f4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassDescriptor.kt @@ -106,9 +106,8 @@ class FunctionClassDescriptor( override fun getDeclaredTypeParameters() = parameters - private inner class FunctionTypeConstructor : AbstractClassTypeConstructor() { - - private val supertypes = storageManager.createLazyValue { + private inner class FunctionTypeConstructor : AbstractClassTypeConstructor(storageManager) { + override fun computeSupertypes(): Collection { val result = ArrayList(2) fun add(packageFragment: PackageFragmentDescriptor, name: Name) { @@ -136,19 +135,20 @@ class FunctionClassDescriptor( add(kotlinPackageFragment, Kind.Function.numberedClassName(arity)) } - result.toReadOnlyList() + return result.toReadOnlyList() } override fun getParameters() = this@FunctionClassDescriptor.parameters - override fun getSupertypes(): Collection = supertypes() - override fun getDeclarationDescriptor() = this@FunctionClassDescriptor override fun isDenotable() = true override fun isFinal() = false override fun getAnnotations() = Annotations.EMPTY override fun toString() = declarationDescriptor.toString() + + override val supertypeLoopChecker: SupertypeLoopChecker + get() = SupertypeLoopChecker.EMPTY } override fun toString() = name.asString() diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SupertypeLoopChecker.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SupertypeLoopChecker.kt index 0d390285882..a14213c0262 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/SupertypeLoopChecker.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/SupertypeLoopChecker.kt @@ -22,17 +22,16 @@ import org.jetbrains.kotlin.types.TypeConstructor interface SupertypeLoopChecker { fun findLoopsInSupertypesAndDisconnect( currentTypeConstructor: TypeConstructor, - superTypes: MutableCollection, + superTypes: Collection, neighbors: (TypeConstructor) -> Iterable, reportLoop: (KotlinType) -> Unit - ) + ): Collection object EMPTY : SupertypeLoopChecker { override fun findLoopsInSupertypesAndDisconnect( currentTypeConstructor: TypeConstructor, - superTypes: MutableCollection, + superTypes: Collection, neighbors: (TypeConstructor) -> Iterable, - reportLoop: (KotlinType) -> Unit) { - } + reportLoop: (KotlinType) -> Unit): Collection = superTypes } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractLazyTypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractLazyTypeParameterDescriptor.java index 53a6ca34b71..1c00529a748 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractLazyTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractLazyTypeParameterDescriptor.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.impl; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.SourceElement; +import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.storage.StorageManager; @@ -32,9 +33,11 @@ public abstract class AbstractLazyTypeParameterDescriptor extends AbstractTypePa @NotNull Variance variance, boolean isReified, int index, - @NotNull SourceElement source + @NotNull SourceElement source, + @NotNull SupertypeLoopChecker supertypeLoopChecker ) { - super(storageManager, containingDeclaration, Annotations.Companion.getEMPTY() /* TODO */, name, variance, isReified, index, source); + super(storageManager, containingDeclaration, Annotations.Companion.getEMPTY() /* TODO */, name, variance, isReified, index, source, + supertypeLoopChecker); } @Override 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 84a5cc7649d..d5a1221db98 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -16,10 +16,9 @@ package org.jetbrains.kotlin.descriptors.impl; -import kotlin.Unit; import kotlin.jvm.functions.Function0; -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; @@ -37,16 +36,12 @@ import java.util.Collections; import java.util.List; public abstract class AbstractTypeParameterDescriptor extends DeclarationDescriptorNonRootImpl implements TypeParameterDescriptor { - public static final List FALLBACK_UPPER_BOUNDS_ON_RECURSION = - Collections.singletonList(ErrorUtils.createErrorType("Recursion while calculating upper bounds")); - private final Variance variance; private final boolean reified; private final int index; private final NotNullLazyValue typeConstructor; private final NotNullLazyValue defaultType; - private final NotNullLazyValue> upperBounds; protected AbstractTypeParameterDescriptor( @NotNull final StorageManager storageManager, @@ -56,7 +51,8 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip @NotNull Variance variance, boolean isReified, int index, - @NotNull SourceElement source + @NotNull SourceElement source, + @NotNull final SupertypeLoopChecker supertypeLoopChecker ) { super(containingDeclaration, annotations, name, source); this.variance = variance; @@ -66,7 +62,7 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip this.typeConstructor = storageManager.createLazyValue(new Function0() { @Override public TypeConstructor invoke() { - return createTypeConstructor(); + return new TypeParameterTypeConstructor(storageManager, supertypeLoopChecker); } }); this.defaultType = storageManager.createLazyValue(new Function0() { @@ -86,106 +82,9 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip ); } }); - this.upperBounds = storageManager.createLazyValueWithPostCompute( - new Function0>() { - @Override - public List invoke() { - return resolveUpperBounds(); - } - }, - new Function1>() { - @Override - public List invoke(Boolean aBoolean) { - return FALLBACK_UPPER_BOUNDS_ON_RECURSION; - } - }, - new Function1, Unit>() { - @Override - public Unit invoke(List types) { - getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect( - getTypeConstructor(), - types, - new Function1>() { - @Override - public Iterable invoke(TypeConstructor typeConstructor) { - if (typeConstructor.getDeclarationDescriptor() instanceof AbstractTypeParameterDescriptor) { - return ((AbstractTypeParameterDescriptor) typeConstructor.getDeclarationDescriptor()) - .resolveUpperBounds(); - } - return typeConstructor.getSupertypes(); - } - }, - new Function1() { - @Override - public Unit invoke(KotlinType type) { - reportCycleError(type); - return Unit.INSTANCE; - } - } - ); - - if (types.isEmpty()) { - types.add(ErrorUtils.createErrorType("Cyclic upper bounds")); - } - - return null; - } - }); } - @NotNull - protected TypeConstructor createTypeConstructor() { - return new TypeConstructor() { - @NotNull - @Override - public Collection getSupertypes() { - return AbstractTypeParameterDescriptor.this.getUpperBounds(); - } - - @NotNull - @Override - public List getParameters() { - return Collections.emptyList(); - } - - @Override - public boolean isFinal() { - return false; - } - - @Override - public boolean isDenotable() { - return true; - } - - @Override - public ClassifierDescriptor getDeclarationDescriptor() { - return AbstractTypeParameterDescriptor.this; - } - - @NotNull - @Override - public Annotations getAnnotations() { - return AbstractTypeParameterDescriptor.this.getAnnotations(); - } - - @NotNull - @Override - public KotlinBuiltIns getBuiltIns() { - return DescriptorUtilsKt.getBuiltIns(AbstractTypeParameterDescriptor.this); - } - - @Override - public String toString() { - return getName().toString(); - } - }; - } - - - @NotNull - protected abstract SupertypeLoopChecker getSupertypeLoopChecker(); - protected abstract void reportCycleError(@NotNull KotlinType type); + protected abstract void reportSupertypeLoopError(@NotNull KotlinType type); @NotNull protected abstract List resolveUpperBounds(); @@ -214,12 +113,12 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip @NotNull @Override public List getUpperBounds() { - return upperBounds.invoke(); + return ((TypeParameterTypeConstructor) getTypeConstructor()).getSupertypes(); } @NotNull @Override - public TypeConstructor getTypeConstructor() { + public final TypeConstructor getTypeConstructor() { return typeConstructor.invoke(); } @@ -240,4 +139,76 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitTypeParameterDescriptor(this, data); } + + private class TypeParameterTypeConstructor extends AbstractTypeConstructor { + + private final SupertypeLoopChecker supertypeLoopChecker; + + public TypeParameterTypeConstructor(@NotNull StorageManager storageManager, SupertypeLoopChecker supertypeLoopChecker) { + super(storageManager); + this.supertypeLoopChecker = supertypeLoopChecker; + } + + @NotNull + @Override + protected Collection computeSupertypes() { + return resolveUpperBounds(); + } + + @NotNull + @Override + public List getParameters() { + return Collections.emptyList(); + } + + @Override + public boolean isFinal() { + return false; + } + + @Override + public boolean isDenotable() { + return true; + } + + @NotNull + @Override + public ClassifierDescriptor getDeclarationDescriptor() { + return AbstractTypeParameterDescriptor.this; + } + + @NotNull + @Override + public Annotations getAnnotations() { + return AbstractTypeParameterDescriptor.this.getAnnotations(); + } + + @NotNull + @Override + public KotlinBuiltIns getBuiltIns() { + return DescriptorUtilsKt.getBuiltIns(AbstractTypeParameterDescriptor.this); + } + + @Override + public String toString() { + return getName().toString(); + } + + @NotNull + @Override + protected SupertypeLoopChecker getSupertypeLoopChecker() { + return supertypeLoopChecker; + } + + @Override + protected void reportSupertypeLoopError(@NotNull KotlinType type) { + AbstractTypeParameterDescriptor.this.reportSupertypeLoopError(type); + } + + @Nullable + @Override + protected KotlinType defaultSupertypeIfEmpty() { + return ErrorUtils.createErrorType("Cyclic upper bounds"); + } + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeParameterDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeParameterDescriptorImpl.java index fb75443810d..85fbcdf7719 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeParameterDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeParameterDescriptorImpl.java @@ -19,21 +19,15 @@ package org.jetbrains.kotlin.descriptors.impl; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.SourceElement; -import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker; -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; +import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.storage.LockBasedStorageManager; import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeConstructor; -import org.jetbrains.kotlin.types.TypeConstructorImpl; import org.jetbrains.kotlin.types.Variance; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns; @@ -41,8 +35,6 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getB public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor { @Nullable private final Function1 reportCycleError; - @NotNull - private final SupertypeLoopChecker supertypeLoopsChecker; public static TypeParameterDescriptor createWithDefaultBound( @NotNull DeclarationDescriptor containingDeclaration, @@ -69,7 +61,7 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor @NotNull SourceElement source ) { return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source, - /* reportCycleError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE); + /* reportSupertypeLoopError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE); } public static TypeParameterDescriptorImpl createForFurtherModification( @@ -101,24 +93,9 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor @Nullable Function1 reportCycleError, @NotNull SupertypeLoopChecker supertypeLoopsChecker ) { - super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source); + super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source, + supertypeLoopsChecker); this.reportCycleError = reportCycleError; - // ? - this.supertypeLoopsChecker = supertypeLoopsChecker; - } - - @NotNull - @Override - protected TypeConstructor createTypeConstructor() { - // TODO: Should we actually pass the annotations on to the type constructor? - return TypeConstructorImpl.createForTypeParameter( - this, - getAnnotations(), - false, - getName().asString(), - Collections.emptyList(), - upperBounds - ); } private void checkInitialized() { @@ -159,14 +136,8 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor } } - @NotNull @Override - protected SupertypeLoopChecker getSupertypeLoopChecker() { - return supertypeLoopsChecker; - } - - @Override - protected void reportCycleError(@NotNull KotlinType type) { + protected void reportSupertypeLoopError(@NotNull KotlinType type) { if (reportCycleError == null) return; reportCycleError.invoke(type); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractClassTypeConstructor.java b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractClassTypeConstructor.java index 39f6b680a48..888326cdfd1 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractClassTypeConstructor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractClassTypeConstructor.java @@ -21,14 +21,23 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.name.FqNameUnsafe; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; +import org.jetbrains.kotlin.storage.StorageManager; -public abstract class AbstractClassTypeConstructor implements TypeConstructor { +import java.util.Collection; +import java.util.Collections; + +public abstract class AbstractClassTypeConstructor extends AbstractTypeConstructor implements TypeConstructor { private boolean hashCodeComputed; private int hashCode; + public AbstractClassTypeConstructor(@NotNull StorageManager storageManager) { + super(storageManager); + } + @Override public final int hashCode() { if (!hashCodeComputed) { @@ -93,4 +102,20 @@ public abstract class AbstractClassTypeConstructor implements TypeConstructor { return !ErrorUtils.isError(descriptor) && !DescriptorUtils.isLocal(descriptor); } + + @NotNull + @Override + protected Collection getAdditionalNeighboursInSupertypeGraph() { + // We suppose that there is an edge from C to A in graph when disconnecting loops in supertypes, + // because such cyclic declarations should be prohibited (see ยง10.2.1 of Kotlin spec) + // class A : B { + // static class C {} + // } + // class B : A.C {} + DeclarationDescriptor containingDeclaration = getDeclarationDescriptor().getContainingDeclaration(); + if (containingDeclaration instanceof ClassDescriptor) { + return Collections.singleton(((ClassDescriptor) containingDeclaration).getDefaultType()); + } + return Collections.emptyList(); + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt new file mode 100644 index 00000000000..92bd7188592 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/types/AbstractTypeConstructor.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2016 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.types + +import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker +import org.jetbrains.kotlin.storage.StorageManager + +abstract class AbstractTypeConstructor(private val storageManager: StorageManager) : TypeConstructor { + override fun getSupertypes() = supertypes().supertypesWithoutCycles + + // In current version diagnostic about loops in supertypes is reported on each vertex (supertype reference) that lies on the cycle. + // To achieve that we store both versions of supertypes --- before and after loops disconnection. + // The first one is used for computation of neighbours in supertypes graph (see Companion.computeNeighbours) + private class Supertypes( + val allSupertypes: Collection) { + // initializer is only needed as a stub for case when 'getSupertypes' is called while 'supertypes' are being calculated + var supertypesWithoutCycles: List = (allSupertypes as? List) ?: allSupertypes.toList() + } + + private val supertypes = storageManager.createLazyValueWithPostCompute( + { Supertypes(computeSupertypes()) }, + { Supertypes(listOf(ERROR_TYPE)) }, + { supertypes -> + // It's important that loops disconnection begins in post-compute phase, because it guarantees that + // when we start calculation supertypes of supertypes (for computing neighbours), they start their disconnection loop process + // either, and as we want to report diagnostic about loops on all declarations they should see consistent version of 'allSupertypes' + var resultWithoutCycles = + supertypeLoopChecker.findLoopsInSupertypesAndDisconnect( + this, supertypes.allSupertypes, + { it.computeNeighbours() }, + { reportSupertypeLoopError(it) }) + + if (resultWithoutCycles.isEmpty()) { + resultWithoutCycles = defaultSupertypeIfEmpty()?.let { listOf(it) }.orEmpty() + } + + supertypes.supertypesWithoutCycles = (resultWithoutCycles as? List) ?: resultWithoutCycles.toList() + }) + + protected abstract fun computeSupertypes(): Collection + protected abstract val supertypeLoopChecker: SupertypeLoopChecker + protected open fun reportSupertypeLoopError(type: KotlinType) {} + protected open fun getAdditionalNeighboursInSupertypeGraph(): Collection = emptyList() + protected open fun defaultSupertypeIfEmpty(): KotlinType? = null + + private companion object { + val ERROR_TYPE = ErrorUtils.createErrorType("Loop in supertypes") + + fun TypeConstructor.computeNeighbours(): Collection = + (this as? AbstractTypeConstructor)?.let { + abstractClassifierDescriptor -> + abstractClassifierDescriptor.supertypes().allSupertypes + + abstractClassifierDescriptor.getAdditionalNeighboursInSupertypeGraph() + } ?: supertypes + } +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructorImpl.java index 9a67b92a232..65e50d66238 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeConstructorImpl.java @@ -56,28 +56,6 @@ public abstract class TypeConstructorImpl extends AnnotatedImpl implements TypeC }; } - @NotNull - public static TypeConstructorImpl createForTypeParameter( - @NotNull TypeParameterDescriptor typeParameterDescriptor, - @NotNull Annotations annotations, - boolean isFinal, - @NotNull String debugName, - @NotNull List parameters, - @NotNull Collection supertypes - ) { - return new TypeConstructorImpl(typeParameterDescriptor, annotations, isFinal, debugName, parameters, supertypes) { - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - }; - } - private final List parameters; private final Collection supertypes; private final String debugName; 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 3f7f6687323..d3770fcdbf2 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 @@ -137,28 +137,6 @@ class DeserializedClassDescriptor( override fun getCompanionObjectDescriptor(): ClassDescriptor? = companionObjectDescriptor() - private fun computeSupertypes(): Collection { - val result = ArrayList(classProto.supertypeCount) - val unresolved = ArrayList(0) - - for (supertypeProto in classProto.supertypes(c.typeTable)) { - val supertype = c.typeDeserializer.type(supertypeProto) - if (supertype.isError) { - unresolved.add(supertype.upperIfFlexible() as? DeserializedType ?: error("Not a deserialized type: $supertype")) - } - else { - result.add(supertype) - } - } - - result.addAll(c.components.additionalSupertypes.forClass(this)) - - if (unresolved.isNotEmpty()) { - c.components.errorReporter.reportIncompleteHierarchy(this, unresolved.map(DeserializedType::getPresentableText)) - } - - return result.toReadOnlyList() - } internal fun hasNestedClass(name: Name): Boolean { return name in nestedClasses.nestedClassNames @@ -170,18 +148,36 @@ class DeserializedClassDescriptor( override fun getDeclaredTypeParameters() = c.typeDeserializer.ownTypeParameters - private inner class DeserializedClassTypeConstructor : AbstractClassTypeConstructor() { - private val supertypes = c.storageManager.createLazyValue { - computeSupertypes() - } - + private inner class DeserializedClassTypeConstructor : AbstractClassTypeConstructor(c.storageManager) { private val parameters = c.storageManager.createLazyValue { this@DeserializedClassDescriptor.computeConstructorTypeParameters() } - override fun getParameters() = parameters() + override fun computeSupertypes(): Collection { + val result = ArrayList(classProto.supertypeCount) + val unresolved = ArrayList(0) - override fun getSupertypes() = supertypes() + for (supertypeProto in classProto.supertypes(c.typeTable)) { + val supertype = c.typeDeserializer.type(supertypeProto) + if (supertype.isError) { + unresolved.add(supertype.upperIfFlexible() as? DeserializedType ?: error("Not a deserialized type: $supertype")) + } + else { + result.add(supertype) + } + } + + result.addAll(c.components.additionalSupertypes.forClass(this@DeserializedClassDescriptor)) + + if (unresolved.isNotEmpty()) { + c.components.errorReporter.reportIncompleteHierarchy( + this@DeserializedClassDescriptor, unresolved.map(DeserializedType::getPresentableText)) + } + + return result.toReadOnlyList() + } + + override fun getParameters() = parameters() override fun isFinal(): Boolean = isFinalClass @@ -192,6 +188,10 @@ class DeserializedClassDescriptor( override fun getAnnotations(): Annotations = Annotations.EMPTY // TODO override fun toString() = getName().toString() + + override val supertypeLoopChecker: SupertypeLoopChecker + // TODO: inject implementation + get() = SupertypeLoopChecker.EMPTY } private inner class DeserializedClassMemberScope : DeserializedMemberScope(c, classProto.functionList, classProto.propertyList) { diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedTypeParameterDescriptor.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedTypeParameterDescriptor.kt index dbdf07d06bb..07f8341c2c6 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedTypeParameterDescriptor.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedTypeParameterDescriptor.kt @@ -34,7 +34,7 @@ class DeserializedTypeParameterDescriptor( index: Int ) : AbstractLazyTypeParameterDescriptor( c.storageManager, c.containingDeclaration, c.nameResolver.getName(proto.name), - Deserialization.variance(proto.variance), proto.reified, index, SourceElement.NO_SOURCE + Deserialization.variance(proto.variance), proto.reified, index, SourceElement.NO_SOURCE, SupertypeLoopChecker.EMPTY ) { private val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) { c.components.annotationAndConstantLoader @@ -54,8 +54,6 @@ class DeserializedTypeParameterDescriptor( } } - override fun getSupertypeLoopChecker() = SupertypeLoopChecker.EMPTY - - override fun reportCycleError(type: KotlinType) = throw IllegalStateException( + override fun reportSupertypeLoopError(type: KotlinType) = throw IllegalStateException( "There should be no cycles for deserialized type parameters, but found for: $this") }