Disconnect loops between upper bounds of type parameters
#KT-9759 Fixed
This commit is contained in:
+1
-1
@@ -416,7 +416,7 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(TYPE_MISMATCH_IN_RANGE, "Type mismatch: incompatible types of range and element checked in it");
|
||||
MAP.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type");
|
||||
MAP.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has itself as an upper bound");
|
||||
MAP.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has cyclic upper bounds");
|
||||
|
||||
MAP.put(MANY_CLASSES_IN_SUPERTYPE_LIST, "Only one class may appear in a supertype list");
|
||||
MAP.put(SUPERTYPE_NOT_A_CLASS_OR_INTERFACE, "Only classes and interfaces may serve as supertypes");
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.SetsKt;
|
||||
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;
|
||||
@@ -410,9 +411,9 @@ public class DescriptorResolver {
|
||||
DeclarationDescriptor containingDescriptor,
|
||||
LexicalWritableScope extensibleScope,
|
||||
LexicalScope scopeForAnnotationsResolve,
|
||||
KtTypeParameter typeParameter,
|
||||
final KtTypeParameter typeParameter,
|
||||
int index,
|
||||
BindingTrace trace
|
||||
final BindingTrace trace
|
||||
) {
|
||||
if (typeParameter.getVariance() != Variance.INVARIANT) {
|
||||
assert !(containingDescriptor instanceof ClassifierDescriptor) : "This method is intended for functions/properties";
|
||||
@@ -429,8 +430,16 @@ public class DescriptorResolver {
|
||||
typeParameter.getVariance(),
|
||||
KtPsiUtil.safeName(typeParameter.getName()),
|
||||
index,
|
||||
KotlinSourceElementKt.toSourceElement(typeParameter)
|
||||
);
|
||||
KotlinSourceElementKt.toSourceElement(typeParameter),
|
||||
new Function1<KotlinType, Void>() {
|
||||
@Override
|
||||
public Void invoke(KotlinType type) {
|
||||
trace.report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeParameter));
|
||||
return null;
|
||||
}
|
||||
},
|
||||
supertypeLoopsResolver
|
||||
);
|
||||
trace.record(BindingContext.TYPE_PARAMETER, typeParameter, typeParameterDescriptor);
|
||||
extensibleScope.addClassifierDescriptor(typeParameterDescriptor);
|
||||
return typeParameterDescriptor;
|
||||
@@ -461,20 +470,6 @@ public class DescriptorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
public KotlinType resolveTypeParameterExtendsBound(
|
||||
@NotNull TypeParameterDescriptor typeParameterDescriptor,
|
||||
@NotNull KtTypeReference extendsBound,
|
||||
LexicalScope scope,
|
||||
BindingTrace trace
|
||||
) {
|
||||
KotlinType type = typeResolver.resolveType(scope, extendsBound, trace, false);
|
||||
if (type.getConstructor().equals(typeParameterDescriptor.getTypeConstructor())) {
|
||||
trace.report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(extendsBound));
|
||||
type = ErrorUtils.createErrorType("Cyclic upper bound: " + type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public void resolveGenericBounds(
|
||||
@NotNull KtTypeParameterListOwner declaration,
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@@ -494,7 +489,7 @@ public class DescriptorResolver {
|
||||
|
||||
KtTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
||||
if (extendsBound != null) {
|
||||
KotlinType type = resolveTypeParameterExtendsBound(typeParameterDescriptor, extendsBound, scope, trace);
|
||||
KotlinType type = typeResolver.resolveType(scope, extendsBound, trace, false);
|
||||
typeParameterDescriptor.addUpperBound(type);
|
||||
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(extendsBound, type));
|
||||
}
|
||||
@@ -523,9 +518,10 @@ public class DescriptorResolver {
|
||||
|
||||
for (TypeParameterDescriptorImpl parameter : parameters) {
|
||||
parameter.addDefaultUpperBound();
|
||||
|
||||
parameter.setInitialized();
|
||||
}
|
||||
|
||||
for (TypeParameterDescriptorImpl parameter : parameters) {
|
||||
checkConflictingUpperBounds(trace, parameter, typeParameters.get(parameter.getIndex()));
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors;
|
||||
|
||||
import kotlin.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -58,6 +60,22 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri
|
||||
this.c.getTrace().record(BindingContext.TYPE_PARAMETER, typeParameter, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected SupertypeLoopChecker getSupertypeLoopChecker() {
|
||||
return c.getSupertypeLoopChecker();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reportCycleError(@NotNull KotlinType type) {
|
||||
for (KtTypeReference typeReference : getAllUpperBounds()) {
|
||||
if (resolveBoundType(typeReference).getConstructor().equals(type.getConstructor())) {
|
||||
c.getTrace().report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeReference));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<KotlinType> resolveUpperBounds() {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T : F?<!>, F : T?> foo1() {}
|
||||
|
||||
fun <T : F?, <!CYCLIC_GENERIC_UPPER_BOUND!>F : E<!>, E : F?> foo2() {}
|
||||
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T<!>, F> foo3() where T : F?, F : T {}
|
||||
|
||||
fun <T, <!CYCLIC_GENERIC_UPPER_BOUND!>F<!>, E> foo4() where T : F?, F : E, E : F? {}
|
||||
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : T?> foo1(): kotlin.Unit
|
||||
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : F?> foo2(): kotlin.Unit
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : T> foo3(): kotlin.Unit
|
||||
public fun </*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : F?> foo4(): kotlin.Unit
|
||||
@@ -0,0 +1,7 @@
|
||||
class A1<T : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>, F : <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>>
|
||||
|
||||
class A2<T : F?, F : <!CYCLIC_GENERIC_UPPER_BOUND!>E<!>, E : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>>
|
||||
|
||||
class A3<T, F> where T : <!CYCLIC_GENERIC_UPPER_BOUND!>F?<!>, F : <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>
|
||||
|
||||
class A4<T, F, E> where T : F?, F : <!CYCLIC_GENERIC_UPPER_BOUND!>E<!>, E : <!CYCLIC_GENERIC_UPPER_BOUND!>F<!>
|
||||
@@ -0,0 +1,29 @@
|
||||
package
|
||||
|
||||
public final class A1</*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor A1</*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class A2</*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor A2</*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class A3</*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor A3</*0*/ T : [ERROR : Cyclic upper bounds], /*1*/ F : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class A4</*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor A4</*0*/ T : F?, /*1*/ F : [ERROR : Cyclic upper bounds], /*2*/ E : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// FILE: XYZ.java
|
||||
public interface XYZ<X extends X> {
|
||||
XYZ foo() {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(xyz: XYZ<*>) = xyz.foo()
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ X : [ERROR : Cyclic upper bounds]> XYZ(/*0*/ function: () -> XYZ<(raw) [ERROR : Cyclic upper bounds]>!): XYZ<X>
|
||||
public fun main(/*0*/ xyz: XYZ<*>): XYZ<(raw) [ERROR : Cyclic upper bounds]>!
|
||||
|
||||
public interface XYZ</*0*/ X : [ERROR : Cyclic upper bounds]> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): XYZ<(raw) [ERROR : Cyclic upper bounds]>!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// FILE: XYZ.java
|
||||
public interface XYZ<X extends Y, Y extends Z, Z extends Y> {
|
||||
XYZ foo() {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main(xyz: XYZ<*, *, *>) = xyz.foo()
|
||||
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public /*synthesized*/ fun </*0*/ X : Y!, /*1*/ Y : [ERROR : Cyclic upper bounds], /*2*/ Z : [ERROR : Cyclic upper bounds]> XYZ(/*0*/ function: () -> XYZ<(raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds]>!): XYZ<X, Y, Z>
|
||||
public fun main(/*0*/ xyz: XYZ<*, *, *>): XYZ<(raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds]>!
|
||||
|
||||
public interface XYZ</*0*/ X : Y!, /*1*/ Y : [ERROR : Cyclic upper bounds], /*2*/ Z : [ERROR : Cyclic upper bounds]> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): XYZ<(raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds], (raw) [ERROR : Cyclic upper bounds]>!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||
fun <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> foo() {}
|
||||
val <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> prop
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
||||
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop
|
||||
@@ -1,4 +1,4 @@
|
||||
package
|
||||
|
||||
public val </*0*/ T : [ERROR : Cyclic upper bound: T?]> prop: [ERROR : No type, no body]
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bound: T?]> foo(): kotlin.Unit
|
||||
public val </*0*/ T : [ERROR : Cyclic upper bounds]> prop: [ERROR : No type, no body]
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds]> foo(): kotlin.Unit
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public final class MyClass</*0*/ T : [ERROR : Cyclic upper bound: T?]> {
|
||||
public constructor MyClass</*0*/ T : [ERROR : Cyclic upper bound: T?]>()
|
||||
public final class MyClass</*0*/ T : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor MyClass</*0*/ T : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package
|
||||
|
||||
public final class MyClass</*0*/ T : [ERROR : Cyclic upper bound: T]> {
|
||||
public constructor MyClass</*0*/ T : [ERROR : Cyclic upper bound: T]>()
|
||||
public final class MyClass</*0*/ T : [ERROR : Cyclic upper bounds]> {
|
||||
public constructor MyClass</*0*/ T : [ERROR : Cyclic upper bounds]>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fun bar() {
|
||||
fun <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> foo() {}
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
||||
<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED_OR_BE_ABSTRACT -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||
class My {
|
||||
fun <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> foo() {}
|
||||
val <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> prop: T
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> foo() {}
|
||||
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop: T
|
||||
}
|
||||
+2
-2
@@ -2,9 +2,9 @@ package
|
||||
|
||||
public final class My {
|
||||
public constructor My()
|
||||
public final val </*0*/ T : [ERROR : Cyclic upper bound: T?]> prop: [ERROR : ?]
|
||||
public final val </*0*/ T : [ERROR : Cyclic upper bounds]> prop: [ERROR : ?]
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun </*0*/ T : [ERROR : Cyclic upper bound: T?]> foo(): kotlin.Unit
|
||||
public final fun </*0*/ T : [ERROR : Cyclic upper bounds]> foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
// !DIAGNOSTICS: -MUST_BE_INITIALIZED -TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||
fun <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T<!>> foo() {}
|
||||
val <T: <!CYCLIC_GENERIC_UPPER_BOUND!>T?<!>> prop: T
|
||||
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T<!>> foo() {}
|
||||
val <<!CYCLIC_GENERIC_UPPER_BOUND!>T: T?<!>> prop: T
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package
|
||||
|
||||
public val </*0*/ T : [ERROR : Cyclic upper bound: T?]> prop: [ERROR : ?]
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bound: T]> foo(): kotlin.Unit
|
||||
public val </*0*/ T : [ERROR : Cyclic upper bounds]> prop: [ERROR : ?]
|
||||
public fun </*0*/ T : [ERROR : Cyclic upper bounds]> foo(): kotlin.Unit
|
||||
|
||||
@@ -6618,6 +6618,27 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/cyclicBounds")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class CyclicBounds extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInCyclicBounds() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/generics/cyclicBounds"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("functions.kt")
|
||||
public void testFunctions() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/cyclicBounds/functions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inClass.kt")
|
||||
public void testInClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/cyclicBounds/inClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/nullability")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -9252,6 +9273,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveRawUpperBound2.kt")
|
||||
public void testRecursiveRawUpperBound2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveRawUpperBound3.kt")
|
||||
public void testRecursiveRawUpperBound3() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/recursiveRawUpperBound3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("samInConstructorWithGenerics.kt")
|
||||
public void testSamInConstructorWithGenerics() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/samInConstructorWithGenerics.kt");
|
||||
|
||||
+6
@@ -54,4 +54,10 @@ class LazyJavaTypeParameterDescriptor(
|
||||
c.typeResolver.transformJavaType(it, TypeUsage.UPPER_BOUND.toAttributes(upperBoundForTypeParameter = this))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSupertypeLoopChecker() = c.components.supertypeLoopChecker
|
||||
|
||||
override fun reportCycleError(type: KotlinType) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
+52
-11
@@ -16,13 +16,11 @@
|
||||
|
||||
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.ReadOnly;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor;
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement;
|
||||
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.scopes.ChainedScope;
|
||||
@@ -96,14 +94,57 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip
|
||||
);
|
||||
}
|
||||
});
|
||||
this.upperBounds = storageManager.createRecursionTolerantLazyValue(new Function0<List<KotlinType>>() {
|
||||
@Override
|
||||
public List<KotlinType> invoke() {
|
||||
return resolveUpperBounds();
|
||||
}
|
||||
}, FALLBACK_UPPER_BOUNDS_ON_RECURSION);
|
||||
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 SupertypeLoopChecker getSupertypeLoopChecker();
|
||||
protected abstract void reportCycleError(@NotNull KotlinType type);
|
||||
|
||||
@NotNull
|
||||
protected abstract List<KotlinType> resolveUpperBounds();
|
||||
|
||||
|
||||
+43
-2
@@ -16,9 +16,12 @@
|
||||
|
||||
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.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -36,6 +39,11 @@ import java.util.List;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
|
||||
|
||||
public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor {
|
||||
@Nullable
|
||||
private final Function1<KotlinType, Void> reportCycleError;
|
||||
@NotNull
|
||||
private final SupertypeLoopChecker supertypeLoopsChecker;
|
||||
|
||||
public static TypeParameterDescriptor createWithDefaultBound(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull Annotations annotations,
|
||||
@@ -60,7 +68,23 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
||||
int index,
|
||||
@NotNull SourceElement source
|
||||
) {
|
||||
return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source);
|
||||
return createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index, source,
|
||||
/* reportCycleError = */ null, SupertypeLoopChecker.EMPTY.INSTANCE);
|
||||
}
|
||||
|
||||
public static TypeParameterDescriptorImpl createForFurtherModification(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull Annotations annotations,
|
||||
boolean reified,
|
||||
@NotNull Variance variance,
|
||||
@NotNull Name name,
|
||||
int index,
|
||||
@NotNull SourceElement source,
|
||||
@Nullable Function1<KotlinType, Void> reportCycleError,
|
||||
@NotNull SupertypeLoopChecker supertypeLoopsResolver
|
||||
) {
|
||||
return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index, source, reportCycleError,
|
||||
supertypeLoopsResolver);
|
||||
}
|
||||
|
||||
private final List<KotlinType> upperBounds = new ArrayList<KotlinType>(1);
|
||||
@@ -73,9 +97,14 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
||||
@NotNull Variance variance,
|
||||
@NotNull Name name,
|
||||
int index,
|
||||
@NotNull SourceElement source
|
||||
@NotNull SourceElement source,
|
||||
@Nullable Function1<KotlinType, Void> reportCycleError,
|
||||
@NotNull SupertypeLoopChecker supertypeLoopsChecker
|
||||
) {
|
||||
super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, annotations, name, variance, reified, index, source);
|
||||
this.reportCycleError = reportCycleError;
|
||||
// ?
|
||||
this.supertypeLoopsChecker = supertypeLoopsChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -130,6 +159,18 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected SupertypeLoopChecker getSupertypeLoopChecker() {
|
||||
return supertypeLoopsChecker;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reportCycleError(@NotNull KotlinType type) {
|
||||
if (reportCycleError == null) return;
|
||||
reportCycleError.invoke(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<KotlinType> resolveUpperBounds() {
|
||||
|
||||
+6
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.serialization.deserialization.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
|
||||
@@ -52,4 +53,9 @@ class DeserializedTypeParameterDescriptor(
|
||||
c.typeDeserializer.type(it, Annotations.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSupertypeLoopChecker() = SupertypeLoopChecker.EMPTY
|
||||
|
||||
override fun reportCycleError(type: KotlinType) = throw IllegalStateException(
|
||||
"There should be no cycles for deserialized type parameters, but found for: $this")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user