Relax rules for type parameters in property receivers

This commit is contained in:
Stanislav Erokhin
2016-01-22 15:34:41 +03:00
parent 30bb8d4828
commit f688b1b786
6 changed files with 91 additions and 11 deletions
@@ -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() }
@@ -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
@@ -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
@@ -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");