Relax rules for type parameters in property receivers
This commit is contained in:
@@ -450,9 +450,26 @@ class DeclarationsChecker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
||||||
for (typeParameter in descriptor.typeParameters) {
|
val allTypeParameters = descriptor.typeParameters.toSet()
|
||||||
if (isTypeParameterUsedInReceiverType(typeParameter, descriptor)) continue
|
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)
|
val typeParameterPsi = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameter)
|
||||||
if (typeParameterPsi is KtTypeParameter) {
|
if (typeParameterPsi is KtTypeParameter) {
|
||||||
trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on(typeParameterPsi))
|
trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on(typeParameterPsi))
|
||||||
@@ -838,14 +855,6 @@ class DeclarationsChecker(
|
|||||||
return !modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD)
|
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) =
|
private fun hasDefaultConstructor(classDescriptor: ClassDescriptor) =
|
||||||
classDescriptor.constructors.any { it.valueParameters.isEmpty() }
|
classDescriptor.constructors.any { it.valueParameters.isEmpty() }
|
||||||
|
|
||||||
|
|||||||
+12
-1
@@ -30,4 +30,15 @@ class C<T1, T2> {
|
|||||||
val <E> E.c: Int get() = 3
|
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 <<!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 <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, 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<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.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 final class C</*0*/ T1, /*1*/ T2> {
|
||||||
public constructor 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 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 interface G {
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
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 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);
|
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")
|
@TestMetadata("repeatedBound.kt")
|
||||||
public void testRepeatedBound() throws Exception {
|
public void testRepeatedBound() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/repeatedBound.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user