Relax rules for type parameters in property receivers
This commit is contained in:
@@ -450,9 +450,26 @@ class DeclarationsChecker(
|
||||
}
|
||||
|
||||
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
||||
for (typeParameter in descriptor.typeParameters) {
|
||||
if (isTypeParameterUsedInReceiverType(typeParameter, descriptor)) continue
|
||||
val allTypeParameters = descriptor.typeParameters.toSet()
|
||||
val allAccessibleTypeParameters = HashSet<TypeParameterDescriptor>()
|
||||
|
||||
fun addAccessibleTypeParametersFromType(type: KotlinType?) {
|
||||
TypeUtils.contains(type) {
|
||||
val declarationDescriptor = it.constructor.declarationDescriptor
|
||||
if (declarationDescriptor is TypeParameterDescriptor && declarationDescriptor in allTypeParameters) {
|
||||
if (allAccessibleTypeParameters.add(declarationDescriptor)) {
|
||||
declarationDescriptor.upperBounds.forEach {
|
||||
addAccessibleTypeParametersFromType(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
addAccessibleTypeParametersFromType(descriptor.extensionReceiverParameter?.type)
|
||||
|
||||
val typeParametersInaccessibleFromReceiver = allTypeParameters - allAccessibleTypeParameters
|
||||
for (typeParameter in typeParametersInaccessibleFromReceiver) {
|
||||
val typeParameterPsi = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameter)
|
||||
if (typeParameterPsi is KtTypeParameter) {
|
||||
trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on(typeParameterPsi))
|
||||
@@ -838,14 +855,6 @@ class DeclarationsChecker(
|
||||
return !modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
||||
}
|
||||
|
||||
private fun isTypeParameterUsedInReceiverType(
|
||||
parameter: TypeParameterDescriptor,
|
||||
descriptor: PropertyDescriptor): Boolean {
|
||||
val receiverParameter = descriptor.extensionReceiverParameter ?: return false
|
||||
|
||||
return TypeUtils.contains(receiverParameter.type) { parameter == it.constructor.declarationDescriptor }
|
||||
}
|
||||
|
||||
private fun hasDefaultConstructor(classDescriptor: ClassDescriptor) =
|
||||
classDescriptor.constructors.any { it.valueParameters.isEmpty() }
|
||||
|
||||
|
||||
+12
-1
@@ -30,4 +30,15 @@ class C<T1, T2> {
|
||||
val <E> E.c: Int get() = 3
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>E<!>> Map<T1, T2>.d: Int get() = 3
|
||||
val <E> Map<T1, E>.e: Int get() = 3
|
||||
}
|
||||
}
|
||||
|
||||
val <T : Enum<T>> T.z1: Int
|
||||
get() = 4
|
||||
|
||||
interface D<T : Enum<T>>
|
||||
|
||||
val <X: D<*>> X.z2: Int
|
||||
get() = 4
|
||||
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>Y<!>> D<*>.z3: Int
|
||||
get() = 4
|
||||
@@ -10,6 +10,9 @@ public val </*0*/ T> kotlin.collections.List<kotlin.collections.Map<kotlin.Int,
|
||||
public val </*0*/ T> kotlin.collections.List<kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.String, out T>>>.g: kotlin.Int
|
||||
public val </*0*/ T> kotlin.collections.List<kotlin.collections.Map<kotlin.Int, kotlin.collections.Map<kotlin.String, in T>>>.h: kotlin.Int
|
||||
public val </*0*/ T> kotlin.collections.List<kotlin.collections.Map<T, kotlin.collections.Map<T, T>>>.i: kotlin.Int
|
||||
public val </*0*/ T : kotlin.Enum<T>> T.z1: kotlin.Int
|
||||
public val </*0*/ X : D<*>> X.z2: kotlin.Int
|
||||
public val </*0*/ Y> D<*>.z3: kotlin.Int
|
||||
|
||||
public final class C</*0*/ T1, /*1*/ T2> {
|
||||
public constructor C</*0*/ T1, /*1*/ T2>()
|
||||
@@ -23,6 +26,12 @@ public final class C</*0*/ T1, /*1*/ T2> {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D</*0*/ T : kotlin.Enum<T>> {
|
||||
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 interface G {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>T : K<!>, K> K.a: Int get() = 4
|
||||
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>T<!>, K> K.b: Int where T : K
|
||||
get() = 4
|
||||
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>T<!>, K> K.c: Int where T : List<K>
|
||||
get() = 4
|
||||
|
||||
val <T, K> K.d: Int where K : T
|
||||
get() = 4
|
||||
|
||||
val <T, K> K.e: Int where K : List<T>
|
||||
get() = 4
|
||||
|
||||
interface G
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>T<!>> G.x1: Int where T : G
|
||||
get() = 4
|
||||
|
||||
|
||||
val <<!TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER!>X<!>, Y, Z> Z.x2: Int where X : Y, Z : Y
|
||||
get() = 4
|
||||
|
||||
val <X, Y: Map<Z, X>, Z: List<List<Y>>> Z.x3: Int
|
||||
get() = 5
|
||||
|
||||
val <X, Y: Map<X, List<Z>>, Z> Map<X, List<Y>>.x4: Int
|
||||
get() = 5
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
package
|
||||
|
||||
public val </*0*/ T : K, /*1*/ K> K.a: kotlin.Int
|
||||
public val </*0*/ T : K, /*1*/ K> K.b: kotlin.Int
|
||||
public val </*0*/ T : kotlin.collections.List<K>, /*1*/ K> K.c: kotlin.Int
|
||||
public val </*0*/ T, /*1*/ K : T> K.d: kotlin.Int
|
||||
public val </*0*/ T, /*1*/ K : kotlin.collections.List<T>> K.e: kotlin.Int
|
||||
public val </*0*/ T : G> G.x1: kotlin.Int
|
||||
public val </*0*/ X : Y, /*1*/ Y, /*2*/ Z : Y> Z.x2: kotlin.Int
|
||||
public val </*0*/ X, /*1*/ Y : kotlin.collections.Map<Z, X>, /*2*/ Z : kotlin.collections.List<kotlin.collections.List<Y>>> Z.x3: kotlin.Int
|
||||
public val </*0*/ X, /*1*/ Y : kotlin.collections.Map<X, kotlin.collections.List<Z>>, /*2*/ Z> kotlin.collections.Map<X, kotlin.collections.List<Y>>.x4: kotlin.Int
|
||||
|
||||
public interface G {
|
||||
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
|
||||
}
|
||||
@@ -18153,6 +18153,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyTypeParametersWithUpperBounds.kt")
|
||||
public void testPropertyTypeParametersWithUpperBounds() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/propertyTypeParametersWithUpperBounds.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("repeatedBound.kt")
|
||||
public void testRepeatedBound() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt");
|
||||
|
||||
Reference in New Issue
Block a user