From 0bc5043c75284c50f88507d99cdcc5a55e562275 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 28 Oct 2015 19:12:30 +0300 Subject: [PATCH] Extract and convert 'findLoopsInSupertypesAndDisconnect' --- .../kotlin/resolve/findLoopsInSupertypes.kt | 61 +++++++++++++++++++ .../lazy/descriptors/LazyClassDescriptor.java | 43 ++++++------- 2 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt new file mode 100644 index 00000000000..6c869dfb122 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/findLoopsInSupertypes.kt @@ -0,0 +1,61 @@ +/* + * 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. + */ + +@file:JvmName("FindLoopsInSupertypes") +package org.jetbrains.kotlin.resolve + +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeConstructor +import org.jetbrains.kotlin.utils.DFS + +fun findLoopsInSupertypesAndDisconnect( + currentTypeConstructor: TypeConstructor, + superTypes: MutableCollection, + neighbors: (TypeConstructor) -> Iterable, + reportLoopAt: (KotlinType) -> Unit +) { + + 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() + reportLoopAt(item) + } + } +} + +private fun isReachable( + from: TypeConstructor, to: TypeConstructor, + neighbors: DFS.Neighbors +): Boolean { + var result = false + DFS.dfs(listOf(from), neighbors, DFS.VisitedWithSet(), object : DFS.AbstractNodeHandler() { + override fun beforeChildren(current: TypeConstructor): Boolean { + if (current == to) { + result = true + return false + } + return true + } + + override fun result() = Unit + }) + + return result +} 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 023288e6031..ecf6388b40a 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 @@ -582,18 +582,27 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection supertypes) { - for (Iterator iterator = supertypes.iterator(); iterator.hasNext(); ) { - KotlinType supertype = iterator.next(); - if (isReachable(supertype.getConstructor(), this, new HashSet())) { - iterator.remove(); + FindLoopsInSupertypes.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); + } - ClassifierDescriptor supertypeDescriptor = supertype.getConstructor().getDeclarationDescriptor(); - if (supertypeDescriptor instanceof ClassDescriptor) { - ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor; - reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass); + return Unit.INSTANCE; + } } - } - } + ); } private void reportCyclicInheritanceHierarchyError( @@ -627,20 +636,6 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } } - private boolean isReachable(TypeConstructor from, TypeConstructor to, Set visited) { - if (!visited.add(from)) return false; - for (KotlinType supertype : getNeighbors(from)) { - TypeConstructor supertypeConstructor = supertype.getConstructor(); - if (supertypeConstructor == to) { - return true; - } - if (isReachable(supertypeConstructor, to, visited)) { - return true; - } - } - return false; - } - private Collection getNeighbors(TypeConstructor from) { // Supertypes + type for container Collection neighbours = new ArrayList(