Extract common logic into AbstractTypeConstructor
Mostly it's about detecting loops in supertypes Test data changes: - Loops are being disconnected in Java classes too - functions.kt: loops disconnection mechanism runs supertypes calculation, so when we start check T it forces F' supertypes calculation, that ends with CYCLIC_GENERIC_UPPER_BOUND reported on F #KT-11287 In Progress
This commit is contained in:
@@ -21,25 +21,27 @@ import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeConstructor
|
import org.jetbrains.kotlin.types.TypeConstructor
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
|
|
||||||
class SupertypeLoopCheckerImpl : SupertypeLoopChecker {
|
class SupertypeLoopCheckerImpl : SupertypeLoopChecker {
|
||||||
override fun findLoopsInSupertypesAndDisconnect(
|
override fun findLoopsInSupertypesAndDisconnect(
|
||||||
currentTypeConstructor: TypeConstructor,
|
currentTypeConstructor: TypeConstructor,
|
||||||
superTypes: MutableCollection<KotlinType>,
|
superTypes: Collection<KotlinType>,
|
||||||
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
||||||
reportLoop: (KotlinType) -> Unit
|
reportLoop: (KotlinType) -> Unit
|
||||||
) {
|
): Collection<KotlinType> {
|
||||||
|
|
||||||
val graph = DFS.Neighbors<TypeConstructor> { node -> neighbors(node).map { it.constructor } }
|
val graph = DFS.Neighbors<TypeConstructor> { node -> neighbors(node).map { it.constructor } }
|
||||||
|
|
||||||
val iterator = superTypes.iterator()
|
val superTypesToRemove = SmartList<KotlinType>()
|
||||||
while (iterator.hasNext()) {
|
|
||||||
val item = iterator.next()
|
for (superType in superTypes) {
|
||||||
if (isReachable(item.constructor, currentTypeConstructor, graph)) {
|
if (isReachable(superType.constructor, currentTypeConstructor, graph)) {
|
||||||
iterator.remove()
|
superTypesToRemove.add(superType)
|
||||||
reportLoop(item)
|
reportLoop(superType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return if (superTypesToRemove.isEmpty()) superTypes else superTypes - superTypesToRemove
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-97
@@ -21,11 +21,9 @@ import com.google.common.collect.Collections2;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||||
import kotlin.Unit;
|
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.Mutable;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.ReadOnly;
|
import org.jetbrains.annotations.ReadOnly;
|
||||||
@@ -568,59 +566,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
|||||||
return parameters.invoke();
|
return parameters.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Supertypes {
|
|
||||||
@Mutable
|
|
||||||
public final Collection<KotlinType> trueSupertypes;
|
|
||||||
@Mutable
|
|
||||||
public final Collection<KotlinType> allSuperTypes;
|
|
||||||
|
|
||||||
private Supertypes(@Mutable @NotNull Collection<KotlinType> allSuperTypes) {
|
|
||||||
this.trueSupertypes = allSuperTypes;
|
|
||||||
this.allSuperTypes = new ArrayList<KotlinType>(allSuperTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public Collection<KotlinType> getAllSupertypes() {
|
|
||||||
return allSuperTypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity {
|
private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity {
|
||||||
private final NotNullLazyValue<Supertypes> supertypes = c.getStorageManager().createLazyValueWithPostCompute(
|
|
||||||
new Function0<Supertypes>() {
|
|
||||||
@Override
|
|
||||||
public Supertypes invoke() {
|
|
||||||
if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
|
|
||||||
return new Supertypes(Collections.<KotlinType>emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
|
||||||
if (classOrObject == null) {
|
|
||||||
return new Supertypes(Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<KotlinType> allSupertypes = c.getDescriptorResolver()
|
|
||||||
.resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
|
|
||||||
c.getTrace());
|
|
||||||
|
|
||||||
return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<Boolean, Supertypes>() {
|
|
||||||
@Override
|
|
||||||
public Supertypes invoke(Boolean firstTime) {
|
|
||||||
return new Supertypes(Collections.<KotlinType>emptyList());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<Supertypes, Unit>() {
|
|
||||||
@Override
|
|
||||||
public Unit invoke(@NotNull Supertypes supertypes) {
|
|
||||||
findAndDisconnectLoopsInTypeHierarchy(supertypes.trueSupertypes);
|
|
||||||
return Unit.INSTANCE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
|
private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
|
||||||
@Override
|
@Override
|
||||||
public List<TypeParameterDescriptor> invoke() {
|
public List<TypeParameterDescriptor> invoke() {
|
||||||
@@ -637,40 +583,37 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
|||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
@NotNull
|
public LazyClassTypeConstructor() {
|
||||||
@Override
|
super(LazyClassDescriptor.this.c.getStorageManager());
|
||||||
public List<TypeParameterDescriptor> getParameters() {
|
|
||||||
return parameters.invoke();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<KotlinType> getSupertypes() {
|
protected Collection<KotlinType> computeSupertypes() {
|
||||||
return supertypes.invoke().trueSupertypes;
|
if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
|
||||||
|
if (classOrObject == null) {
|
||||||
|
return Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<KotlinType> allSupertypes =
|
||||||
|
c.getDescriptorResolver()
|
||||||
|
.resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
|
||||||
|
c.getTrace());
|
||||||
|
|
||||||
|
return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection<KotlinType> supertypes) {
|
@Override
|
||||||
c.getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect(
|
protected void reportSupertypeLoopError(@NotNull KotlinType type) {
|
||||||
typeConstructor, supertypes,
|
ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||||
new Function1<TypeConstructor, Iterable<? extends KotlinType>>() {
|
if (supertypeDescriptor instanceof ClassDescriptor) {
|
||||||
@Override
|
ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
|
||||||
public Iterable<? extends KotlinType> invoke(TypeConstructor typeConstructor) {
|
reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass);
|
||||||
return getNeighbors(typeConstructor);
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<KotlinType, Unit>() {
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportCyclicInheritanceHierarchyError(
|
private void reportCyclicInheritanceHierarchyError(
|
||||||
@@ -704,22 +647,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<KotlinType> getNeighbors(TypeConstructor from) {
|
@NotNull
|
||||||
// Supertypes + type for container
|
@Override
|
||||||
Collection<KotlinType> neighbours = new ArrayList<KotlinType>(
|
protected SupertypeLoopChecker getSupertypeLoopChecker() {
|
||||||
from instanceof LazyClassTypeConstructor
|
return c.getSupertypeLoopChecker();
|
||||||
? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes()
|
}
|
||||||
: from.getSupertypes()
|
|
||||||
);
|
|
||||||
|
|
||||||
ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor();
|
@NotNull
|
||||||
if (fromDescriptor != null) {
|
@Override
|
||||||
DeclarationDescriptor container = fromDescriptor.getContainingDeclaration();
|
public List<TypeParameterDescriptor> getParameters() {
|
||||||
if (container instanceof ClassDescriptor) {
|
return parameters.invoke();
|
||||||
neighbours.add(((ClassDescriptor) container).getDefaultType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return neighbours;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+3
-9
@@ -52,22 +52,16 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri
|
|||||||
typeParameter.getVariance(),
|
typeParameter.getVariance(),
|
||||||
typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD),
|
typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD),
|
||||||
index,
|
index,
|
||||||
KotlinSourceElementKt.toSourceElement(typeParameter)
|
KotlinSourceElementKt.toSourceElement(typeParameter),
|
||||||
);
|
c.getSupertypeLoopChecker());
|
||||||
this.c = c;
|
this.c = c;
|
||||||
this.typeParameter = typeParameter;
|
this.typeParameter = typeParameter;
|
||||||
|
|
||||||
this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this);
|
this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
protected SupertypeLoopChecker getSupertypeLoopChecker() {
|
protected void reportSupertypeLoopError(@NotNull KotlinType type) {
|
||||||
return c.getSupertypeLoopChecker();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void reportCycleError(@NotNull KotlinType type) {
|
|
||||||
for (KtTypeReference typeReference : getAllUpperBounds()) {
|
for (KtTypeReference typeReference : getAllUpperBounds()) {
|
||||||
if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) {
|
if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) {
|
||||||
c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference));
|
c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference));
|
||||||
|
|||||||
+2
-5
@@ -1,8 +1,6 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public/*package*/ interface A : C {
|
public/*package*/ interface A {
|
||||||
public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit
|
|
||||||
public abstract override /*1*/ /*fake_override*/ fun baz(): kotlin.Unit
|
|
||||||
public abstract fun foo(): kotlin.Unit
|
public abstract fun foo(): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,7 +8,6 @@ public interface B {
|
|||||||
public abstract fun bar(): kotlin.Unit
|
public abstract fun bar(): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
public/*package*/ interface C : B {
|
public/*package*/ interface C {
|
||||||
public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit
|
|
||||||
public abstract fun baz(): kotlin.Unit
|
public abstract fun baz(): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public/*package*/ open class J : K {
|
public/*package*/ open class J {
|
||||||
public/*package*/ constructor J()
|
public/*package*/ constructor J()
|
||||||
public final override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit
|
|
||||||
public/*package*/ open fun foo(): kotlin.Unit
|
public/*package*/ open fun foo(): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -5,10 +5,9 @@ public open class I {
|
|||||||
public final fun foo(): kotlin.Unit
|
public final fun foo(): kotlin.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
public/*package*/ open class J : I {
|
public/*package*/ open class J {
|
||||||
public/*package*/ constructor J()
|
public/*package*/ constructor J()
|
||||||
public/*package*/ open fun bar(): kotlin.Unit
|
public/*package*/ open fun bar(): kotlin.Unit
|
||||||
public final override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public open class K {
|
public open class K {
|
||||||
|
|||||||
+2
-2
@@ -3,9 +3,9 @@ package
|
|||||||
public interface ExceptionTracker {
|
public interface ExceptionTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public/*package*/ open class LockBasedStorageManager : StorageManager {
|
public/*package*/ open class LockBasedStorageManager {
|
||||||
public/*package*/ constructor 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/*package*/ interface ExceptionHandlingStrategy {
|
||||||
public abstract fun bar(): kotlin.Unit
|
public abstract fun bar(): kotlin.Unit
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T : F?<!>, F : T?> foo1() {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T : F?<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>F : T?<!>> foo1() {}
|
||||||
|
|
||||||
fun <T : F?, <!CYCLIC_GENERIC_UPPER_BOUND!>F : E<!>, E : F?> foo2() {}
|
fun <T : F?, <!CYCLIC_GENERIC_UPPER_BOUND!>F : E<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>E : F?<!>> foo2() {}
|
||||||
|
|
||||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T<!>, F> foo3() where T : F?, F : T {}
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>F<!>> foo3() where T : F?, F : T {}
|
||||||
|
|
||||||
fun <T, <!CYCLIC_GENERIC_UPPER_BOUND!>F<!>, E> foo4() where T : F?, F : E, E : F? {}
|
fun <T, <!CYCLIC_GENERIC_UPPER_BOUND!>F<!>, <!CYCLIC_GENERIC_UPPER_BOUND!>E<!>> foo4() where T : F?, F : E, E : F? {}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : T?> foo1(): kotlin.Unit
|
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]> foo1(): kotlin.Unit
|
||||||
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : F?> foo2(): kotlin.Unit
|
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]> foo2(): kotlin.Unit
|
||||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : T> foo3(): kotlin.Unit
|
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]> foo3(): kotlin.Unit
|
||||||
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : F?> foo4(): kotlin.Unit
|
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]> foo4(): kotlin.Unit
|
||||||
|
|||||||
+17
-17
@@ -128,16 +128,15 @@ class LazyJavaClassDescriptor(
|
|||||||
|
|
||||||
override fun toString() = "lazy java class $fqName"
|
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 {
|
private val parameters = c.storageManager.createLazyValue {
|
||||||
this@LazyJavaClassDescriptor.computeConstructorTypeParameters()
|
this@LazyJavaClassDescriptor.computeConstructorTypeParameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParameters(): List<TypeParameterDescriptor> = parameters()
|
override fun getParameters(): List<TypeParameterDescriptor> = parameters()
|
||||||
|
|
||||||
private val supertypes = c.storageManager.createLazyValue<Collection<KotlinType>> {
|
override fun computeSupertypes(): Collection<KotlinType> {
|
||||||
val javaTypes = jClass.getSupertypes()
|
val javaTypes = jClass.supertypes
|
||||||
val result = ArrayList<KotlinType>(javaTypes.size)
|
val result = ArrayList<KotlinType>(javaTypes.size)
|
||||||
val incomplete = ArrayList<JavaType>(0)
|
val incomplete = ArrayList<JavaType>(0)
|
||||||
|
|
||||||
@@ -145,12 +144,12 @@ class LazyJavaClassDescriptor(
|
|||||||
|
|
||||||
for (javaType in javaTypes) {
|
for (javaType in javaTypes) {
|
||||||
val jetType = c.typeResolver.transformJavaType(javaType, TypeUsage.SUPERTYPE.toAttributes())
|
val jetType = c.typeResolver.transformJavaType(javaType, TypeUsage.SUPERTYPE.toAttributes())
|
||||||
if (jetType.isError()) {
|
if (jetType.isError) {
|
||||||
incomplete.add(javaType)
|
incomplete.add(javaType)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jetType.getConstructor() == purelyImplementedSupertype?.getConstructor()) {
|
if (jetType.constructor == purelyImplementedSupertype?.constructor) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,12 +161,12 @@ class LazyJavaClassDescriptor(
|
|||||||
result.addIfNotNull(purelyImplementedSupertype)
|
result.addIfNotNull(purelyImplementedSupertype)
|
||||||
|
|
||||||
if (incomplete.isNotEmpty()) {
|
if (incomplete.isNotEmpty()) {
|
||||||
c.components.errorReporter.reportIncompleteHierarchy(getDeclarationDescriptor(), incomplete.map { javaType ->
|
c.components.errorReporter.reportIncompleteHierarchy(declarationDescriptor, incomplete.map { javaType ->
|
||||||
(javaType as JavaClassifierType).getPresentableText()
|
(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? {
|
private fun getPurelyImplementedSupertype(): KotlinType? {
|
||||||
@@ -179,10 +178,10 @@ class LazyJavaClassDescriptor(
|
|||||||
|
|
||||||
val classDescriptor = c.module.builtIns.getBuiltInClassByFqNameNullable(purelyImplementedFqName) ?: return null
|
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 {
|
val parametersAsTypeProjections = getTypeConstructor().parameters.map {
|
||||||
parameter -> TypeProjectionImpl(Variance.INVARIANT, parameter.getDefaultType())
|
parameter -> TypeProjectionImpl(Variance.INVARIANT, parameter.defaultType)
|
||||||
}
|
}
|
||||||
|
|
||||||
return KotlinTypeImpl.create(
|
return KotlinTypeImpl.create(
|
||||||
@@ -192,17 +191,18 @@ class LazyJavaClassDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPurelyImplementsFqNameFromAnnotation(): FqName? {
|
private fun getPurelyImplementsFqNameFromAnnotation(): FqName? {
|
||||||
val annotation = this@LazyJavaClassDescriptor.
|
val annotation =
|
||||||
getAnnotations().
|
this@LazyJavaClassDescriptor.getAnnotations().findAnnotation(JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION)
|
||||||
findAnnotation(JvmAnnotationNames.PURELY_IMPLEMENTS_ANNOTATION) ?: return null
|
?: 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
|
if (!isValidJavaFqName(fqNameString)) return null
|
||||||
|
|
||||||
return FqName(fqNameString)
|
return FqName(fqNameString)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSupertypes(): Collection<KotlinType> = supertypes()
|
override val supertypeLoopChecker: SupertypeLoopChecker
|
||||||
|
get() = c.components.supertypeLoopChecker
|
||||||
|
|
||||||
override fun getAnnotations() = Annotations.EMPTY
|
override fun getAnnotations() = Annotations.EMPTY
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.java.lazy.descriptors
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
@@ -39,7 +40,7 @@ class LazyJavaTypeParameterDescriptor(
|
|||||||
Variance.INVARIANT,
|
Variance.INVARIANT,
|
||||||
/* isReified = */ false,
|
/* isReified = */ false,
|
||||||
index,
|
index,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE, c.components.supertypeLoopChecker
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun resolveUpperBounds(): List<KotlinType> {
|
override fun resolveUpperBounds(): List<KotlinType> {
|
||||||
@@ -55,9 +56,7 @@ class LazyJavaTypeParameterDescriptor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSupertypeLoopChecker() = c.components.supertypeLoopChecker
|
override fun reportSupertypeLoopError(type: KotlinType) {
|
||||||
|
|
||||||
override fun reportCycleError(type: KotlinType) {
|
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -106,9 +106,8 @@ class FunctionClassDescriptor(
|
|||||||
|
|
||||||
override fun getDeclaredTypeParameters() = parameters
|
override fun getDeclaredTypeParameters() = parameters
|
||||||
|
|
||||||
private inner class FunctionTypeConstructor : AbstractClassTypeConstructor() {
|
private inner class FunctionTypeConstructor : AbstractClassTypeConstructor(storageManager) {
|
||||||
|
override fun computeSupertypes(): Collection<KotlinType> {
|
||||||
private val supertypes = storageManager.createLazyValue {
|
|
||||||
val result = ArrayList<KotlinType>(2)
|
val result = ArrayList<KotlinType>(2)
|
||||||
|
|
||||||
fun add(packageFragment: PackageFragmentDescriptor, name: Name) {
|
fun add(packageFragment: PackageFragmentDescriptor, name: Name) {
|
||||||
@@ -136,19 +135,20 @@ class FunctionClassDescriptor(
|
|||||||
add(kotlinPackageFragment, Kind.Function.numberedClassName(arity))
|
add(kotlinPackageFragment, Kind.Function.numberedClassName(arity))
|
||||||
}
|
}
|
||||||
|
|
||||||
result.toReadOnlyList()
|
return result.toReadOnlyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParameters() = this@FunctionClassDescriptor.parameters
|
override fun getParameters() = this@FunctionClassDescriptor.parameters
|
||||||
|
|
||||||
override fun getSupertypes(): Collection<KotlinType> = supertypes()
|
|
||||||
|
|
||||||
override fun getDeclarationDescriptor() = this@FunctionClassDescriptor
|
override fun getDeclarationDescriptor() = this@FunctionClassDescriptor
|
||||||
override fun isDenotable() = true
|
override fun isDenotable() = true
|
||||||
override fun isFinal() = false
|
override fun isFinal() = false
|
||||||
override fun getAnnotations() = Annotations.EMPTY
|
override fun getAnnotations() = Annotations.EMPTY
|
||||||
|
|
||||||
override fun toString() = declarationDescriptor.toString()
|
override fun toString() = declarationDescriptor.toString()
|
||||||
|
|
||||||
|
override val supertypeLoopChecker: SupertypeLoopChecker
|
||||||
|
get() = SupertypeLoopChecker.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = name.asString()
|
override fun toString() = name.asString()
|
||||||
|
|||||||
@@ -22,17 +22,16 @@ import org.jetbrains.kotlin.types.TypeConstructor
|
|||||||
interface SupertypeLoopChecker {
|
interface SupertypeLoopChecker {
|
||||||
fun findLoopsInSupertypesAndDisconnect(
|
fun findLoopsInSupertypesAndDisconnect(
|
||||||
currentTypeConstructor: TypeConstructor,
|
currentTypeConstructor: TypeConstructor,
|
||||||
superTypes: MutableCollection<KotlinType>,
|
superTypes: Collection<KotlinType>,
|
||||||
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
||||||
reportLoop: (KotlinType) -> Unit
|
reportLoop: (KotlinType) -> Unit
|
||||||
)
|
): Collection<KotlinType>
|
||||||
|
|
||||||
object EMPTY : SupertypeLoopChecker {
|
object EMPTY : SupertypeLoopChecker {
|
||||||
override fun findLoopsInSupertypesAndDisconnect(
|
override fun findLoopsInSupertypesAndDisconnect(
|
||||||
currentTypeConstructor: TypeConstructor,
|
currentTypeConstructor: TypeConstructor,
|
||||||
superTypes: MutableCollection<KotlinType>,
|
superTypes: Collection<KotlinType>,
|
||||||
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
neighbors: (TypeConstructor) -> Iterable<KotlinType>,
|
||||||
reportLoop: (KotlinType) -> Unit) {
|
reportLoop: (KotlinType) -> Unit): Collection<KotlinType> = superTypes
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.impl;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement;
|
import org.jetbrains.kotlin.descriptors.SourceElement;
|
||||||
|
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.storage.StorageManager;
|
import org.jetbrains.kotlin.storage.StorageManager;
|
||||||
@@ -32,9 +33,11 @@ public abstract class AbstractLazyTypeParameterDescriptor extends AbstractTypePa
|
|||||||
@NotNull Variance variance,
|
@NotNull Variance variance,
|
||||||
boolean isReified,
|
boolean isReified,
|
||||||
int index,
|
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
|
@Override
|
||||||
|
|||||||
+79
-108
@@ -16,10 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.descriptors.impl;
|
package org.jetbrains.kotlin.descriptors.impl;
|
||||||
|
|
||||||
import kotlin.Unit;
|
|
||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.jvm.functions.Function1;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
@@ -37,16 +36,12 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class AbstractTypeParameterDescriptor extends DeclarationDescriptorNonRootImpl implements TypeParameterDescriptor {
|
public abstract class AbstractTypeParameterDescriptor extends DeclarationDescriptorNonRootImpl implements TypeParameterDescriptor {
|
||||||
public static final List<KotlinType> FALLBACK_UPPER_BOUNDS_ON_RECURSION =
|
|
||||||
Collections.singletonList(ErrorUtils.createErrorType("Recursion while calculating upper bounds"));
|
|
||||||
|
|
||||||
private final Variance variance;
|
private final Variance variance;
|
||||||
private final boolean reified;
|
private final boolean reified;
|
||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
private final NotNullLazyValue<TypeConstructor> typeConstructor;
|
private final NotNullLazyValue<TypeConstructor> typeConstructor;
|
||||||
private final NotNullLazyValue<KotlinType> defaultType;
|
private final NotNullLazyValue<KotlinType> defaultType;
|
||||||
private final NotNullLazyValue<List<KotlinType>> upperBounds;
|
|
||||||
|
|
||||||
protected AbstractTypeParameterDescriptor(
|
protected AbstractTypeParameterDescriptor(
|
||||||
@NotNull final StorageManager storageManager,
|
@NotNull final StorageManager storageManager,
|
||||||
@@ -56,7 +51,8 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
|||||||
@NotNull Variance variance,
|
@NotNull Variance variance,
|
||||||
boolean isReified,
|
boolean isReified,
|
||||||
int index,
|
int index,
|
||||||
@NotNull SourceElement source
|
@NotNull SourceElement source,
|
||||||
|
@NotNull final SupertypeLoopChecker supertypeLoopChecker
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, annotations, name, source);
|
super(containingDeclaration, annotations, name, source);
|
||||||
this.variance = variance;
|
this.variance = variance;
|
||||||
@@ -66,7 +62,7 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
|||||||
this.typeConstructor = storageManager.createLazyValue(new Function0<TypeConstructor>() {
|
this.typeConstructor = storageManager.createLazyValue(new Function0<TypeConstructor>() {
|
||||||
@Override
|
@Override
|
||||||
public TypeConstructor invoke() {
|
public TypeConstructor invoke() {
|
||||||
return createTypeConstructor();
|
return new TypeParameterTypeConstructor(storageManager, supertypeLoopChecker);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.defaultType = storageManager.createLazyValue(new Function0<KotlinType>() {
|
this.defaultType = storageManager.createLazyValue(new Function0<KotlinType>() {
|
||||||
@@ -86,106 +82,9 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.upperBounds = storageManager.createLazyValueWithPostCompute(
|
|
||||||
new Function0<List<KotlinType>>() {
|
|
||||||
@Override
|
|
||||||
public List<KotlinType> invoke() {
|
|
||||||
return resolveUpperBounds();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<Boolean, List<KotlinType>>() {
|
|
||||||
@Override
|
|
||||||
public List<KotlinType> invoke(Boolean aBoolean) {
|
|
||||||
return FALLBACK_UPPER_BOUNDS_ON_RECURSION;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<List<KotlinType>, Unit>() {
|
|
||||||
@Override
|
|
||||||
public Unit invoke(List<KotlinType> types) {
|
|
||||||
getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect(
|
|
||||||
getTypeConstructor(),
|
|
||||||
types,
|
|
||||||
new Function1<TypeConstructor, Iterable<? extends KotlinType>>() {
|
|
||||||
@Override
|
|
||||||
public Iterable<? extends KotlinType> invoke(TypeConstructor typeConstructor) {
|
|
||||||
if (typeConstructor.getDeclarationDescriptor() instanceof AbstractTypeParameterDescriptor) {
|
|
||||||
return ((AbstractTypeParameterDescriptor) typeConstructor.getDeclarationDescriptor())
|
|
||||||
.resolveUpperBounds();
|
|
||||||
}
|
|
||||||
return typeConstructor.getSupertypes();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<KotlinType, Unit>() {
|
|
||||||
@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 abstract void reportSupertypeLoopError(@NotNull KotlinType type);
|
||||||
protected TypeConstructor createTypeConstructor() {
|
|
||||||
return new TypeConstructor() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Collection<KotlinType> getSupertypes() {
|
|
||||||
return AbstractTypeParameterDescriptor.this.getUpperBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public List<TypeParameterDescriptor> 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);
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected abstract List<KotlinType> resolveUpperBounds();
|
protected abstract List<KotlinType> resolveUpperBounds();
|
||||||
@@ -214,12 +113,12 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<KotlinType> getUpperBounds() {
|
public List<KotlinType> getUpperBounds() {
|
||||||
return upperBounds.invoke();
|
return ((TypeParameterTypeConstructor) getTypeConstructor()).getSupertypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeConstructor getTypeConstructor() {
|
public final TypeConstructor getTypeConstructor() {
|
||||||
return typeConstructor.invoke();
|
return typeConstructor.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,4 +139,76 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
|||||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||||
return visitor.visitTypeParameterDescriptor(this, 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<KotlinType> computeSupertypes() {
|
||||||
|
return resolveUpperBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<TypeParameterDescriptor> 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-34
@@ -19,21 +19,15 @@ package org.jetbrains.kotlin.descriptors.impl;
|
|||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement;
|
|
||||||
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker;
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
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 org.jetbrains.kotlin.types.Variance;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
|
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 {
|
public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor {
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Function1<KotlinType, Void> reportCycleError;
|
private final Function1<KotlinType, Void> reportCycleError;
|
||||||
@NotNull
|
|
||||||
private final SupertypeLoopChecker supertypeLoopsChecker;
|
|
||||||
|
|
||||||
public static TypeParameterDescriptor createWithDefaultBound(
|
public static TypeParameterDescriptor createWithDefaultBound(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@@ -69,7 +61,7 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
|||||||
@NotNull SourceElement source
|
@NotNull SourceElement source
|
||||||
) {
|
) {
|
||||||
return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
|
return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
|
||||||
/* reportCycleError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
|
/* reportSupertypeLoopError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeParameterDescriptorImpl createForFurtherModification(
|
public static TypeParameterDescriptorImpl createForFurtherModification(
|
||||||
@@ -101,24 +93,9 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
|||||||
@Nullable Function1<KotlinType, Void> reportCycleError,
|
@Nullable Function1<KotlinType, Void> reportCycleError,
|
||||||
@NotNull SupertypeLoopChecker supertypeLoopsChecker
|
@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.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.<TypeParameterDescriptor>emptyList(),
|
|
||||||
upperBounds
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkInitialized() {
|
private void checkInitialized() {
|
||||||
@@ -159,14 +136,8 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
protected SupertypeLoopChecker getSupertypeLoopChecker() {
|
protected void reportSupertypeLoopError(@NotNull KotlinType type) {
|
||||||
return supertypeLoopsChecker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void reportCycleError(@NotNull KotlinType type) {
|
|
||||||
if (reportCycleError == null) return;
|
if (reportCycleError == null) return;
|
||||||
reportCycleError.invoke(type);
|
reportCycleError.invoke(type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,14 +21,23 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
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 boolean hashCodeComputed;
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
public AbstractClassTypeConstructor(@NotNull StorageManager storageManager) {
|
||||||
|
super(storageManager);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public final int hashCode() {
|
||||||
if (!hashCodeComputed) {
|
if (!hashCodeComputed) {
|
||||||
@@ -93,4 +102,20 @@ public abstract class AbstractClassTypeConstructor implements TypeConstructor {
|
|||||||
return !ErrorUtils.isError(descriptor) &&
|
return !ErrorUtils.isError(descriptor) &&
|
||||||
!DescriptorUtils.isLocal(descriptor);
|
!DescriptorUtils.isLocal(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected Collection<KotlinType> 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<KotlinType>) {
|
||||||
|
// initializer is only needed as a stub for case when 'getSupertypes' is called while 'supertypes' are being calculated
|
||||||
|
var supertypesWithoutCycles: List<KotlinType> = (allSupertypes as? List<KotlinType>) ?: 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<KotlinType>) ?: resultWithoutCycles.toList()
|
||||||
|
})
|
||||||
|
|
||||||
|
protected abstract fun computeSupertypes(): Collection<KotlinType>
|
||||||
|
protected abstract val supertypeLoopChecker: SupertypeLoopChecker
|
||||||
|
protected open fun reportSupertypeLoopError(type: KotlinType) {}
|
||||||
|
protected open fun getAdditionalNeighboursInSupertypeGraph(): Collection<KotlinType> = emptyList()
|
||||||
|
protected open fun defaultSupertypeIfEmpty(): KotlinType? = null
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val ERROR_TYPE = ErrorUtils.createErrorType("Loop in supertypes")
|
||||||
|
|
||||||
|
fun TypeConstructor.computeNeighbours(): Collection<KotlinType> =
|
||||||
|
(this as? AbstractTypeConstructor)?.let {
|
||||||
|
abstractClassifierDescriptor ->
|
||||||
|
abstractClassifierDescriptor.supertypes().allSupertypes +
|
||||||
|
abstractClassifierDescriptor.getAdditionalNeighboursInSupertypeGraph()
|
||||||
|
} ?: supertypes
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<? extends TypeParameterDescriptor> parameters,
|
|
||||||
@NotNull Collection<KotlinType> 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<TypeParameterDescriptor> parameters;
|
private final List<TypeParameterDescriptor> parameters;
|
||||||
private final Collection<KotlinType> supertypes;
|
private final Collection<KotlinType> supertypes;
|
||||||
private final String debugName;
|
private final String debugName;
|
||||||
|
|||||||
+29
-29
@@ -137,28 +137,6 @@ class DeserializedClassDescriptor(
|
|||||||
|
|
||||||
override fun getCompanionObjectDescriptor(): ClassDescriptor? = companionObjectDescriptor()
|
override fun getCompanionObjectDescriptor(): ClassDescriptor? = companionObjectDescriptor()
|
||||||
|
|
||||||
private fun computeSupertypes(): Collection<KotlinType> {
|
|
||||||
val result = ArrayList<KotlinType>(classProto.supertypeCount)
|
|
||||||
val unresolved = ArrayList<DeserializedType>(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 {
|
internal fun hasNestedClass(name: Name): Boolean {
|
||||||
return name in nestedClasses.nestedClassNames
|
return name in nestedClasses.nestedClassNames
|
||||||
@@ -170,18 +148,36 @@ class DeserializedClassDescriptor(
|
|||||||
|
|
||||||
override fun getDeclaredTypeParameters() = c.typeDeserializer.ownTypeParameters
|
override fun getDeclaredTypeParameters() = c.typeDeserializer.ownTypeParameters
|
||||||
|
|
||||||
private inner class DeserializedClassTypeConstructor : AbstractClassTypeConstructor() {
|
private inner class DeserializedClassTypeConstructor : AbstractClassTypeConstructor(c.storageManager) {
|
||||||
private val supertypes = c.storageManager.createLazyValue {
|
|
||||||
computeSupertypes()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val parameters = c.storageManager.createLazyValue {
|
private val parameters = c.storageManager.createLazyValue {
|
||||||
this@DeserializedClassDescriptor.computeConstructorTypeParameters()
|
this@DeserializedClassDescriptor.computeConstructorTypeParameters()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getParameters() = parameters()
|
override fun computeSupertypes(): Collection<KotlinType> {
|
||||||
|
val result = ArrayList<KotlinType>(classProto.supertypeCount)
|
||||||
|
val unresolved = ArrayList<DeserializedType>(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
|
override fun isFinal(): Boolean = isFinalClass
|
||||||
|
|
||||||
@@ -192,6 +188,10 @@ class DeserializedClassDescriptor(
|
|||||||
override fun getAnnotations(): Annotations = Annotations.EMPTY // TODO
|
override fun getAnnotations(): Annotations = Annotations.EMPTY // TODO
|
||||||
|
|
||||||
override fun toString() = getName().toString()
|
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) {
|
private inner class DeserializedClassMemberScope : DeserializedMemberScope(c, classProto.functionList, classProto.propertyList) {
|
||||||
|
|||||||
+2
-4
@@ -34,7 +34,7 @@ class DeserializedTypeParameterDescriptor(
|
|||||||
index: Int
|
index: Int
|
||||||
) : AbstractLazyTypeParameterDescriptor(
|
) : AbstractLazyTypeParameterDescriptor(
|
||||||
c.storageManager, c.containingDeclaration, c.nameResolver.getName(proto.name),
|
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) {
|
private val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
|
||||||
c.components.annotationAndConstantLoader
|
c.components.annotationAndConstantLoader
|
||||||
@@ -54,8 +54,6 @@ class DeserializedTypeParameterDescriptor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSupertypeLoopChecker() = SupertypeLoopChecker.EMPTY
|
override fun reportSupertypeLoopError(type: KotlinType) = throw IllegalStateException(
|
||||||
|
|
||||||
override fun reportCycleError(type: KotlinType) = throw IllegalStateException(
|
|
||||||
"There should be no cycles for deserialized type parameters, but found for: $this")
|
"There should be no cycles for deserialized type parameters, but found for: $this")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user