From 77353d4a56c9c3938c392d27866b68c241388dde Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 19 Jul 2012 14:33:44 +0400 Subject: [PATCH] LR: Detecting and disconnecting loops in type hierarchy --- .../resolve/lazy/LazyClassDescriptor.java | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java index 50550019e3f..613e7966fb6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LazyClassDescriptor.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -39,10 +40,7 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.TypeUtils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author abreslav @@ -326,13 +324,38 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes .resolveSupertypes(getScopeForClassHeaderResolution(), classOrObject, resolveSession.getTrace()); - this.supertypes = Collections2.filter(allSupertypes, VALID_SUPERTYPE); + List validSupertypes = Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)); + this.supertypes = validSupertypes; + findAndDisconnectLoopsInTypeHierarchy(validSupertypes); } } } return supertypes; } + private void findAndDisconnectLoopsInTypeHierarchy(List supertypes) { + for (Iterator iterator = supertypes.iterator(); iterator.hasNext(); ) { + JetType supertype = iterator.next(); + if (isReachable(supertype.getConstructor(), this, new HashSet())) { + iterator.remove(); + } + } + } + + private boolean isReachable(TypeConstructor from, TypeConstructor to, Set visited) { + if (!visited.add(from)) return false; + for (JetType supertype : from.getSupertypes()) { + TypeConstructor supertypeConstructor = supertype.getConstructor(); + if (supertypeConstructor == to) { + return true; + } + if (isReachable(supertypeConstructor, to, visited)) { + return true; + } + } + return false; + } + @Override public boolean isSealed() { return !getModality().isOverridable();