Skip to content

Commit d9744c8

Browse files
authored
Merge pull request #11017 from smowton/smowton/fix/kotlin-wildcard-suppression-annotation
Kotlin: fix wildcard suppression where the annotation applies to a parent type/argument.
2 parents 1914a11 + d6e2f5f commit d9744c8

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ open class KotlinFileExtractor(
691691
null
692692
} ?: vp.type
693693
val javaType = (vp.parent as? IrFunction)?.let { getJavaCallable(it)?.let { jCallable -> getJavaValueParameterType(jCallable, idx) } }
694-
val typeWithWildcards = addJavaLoweringWildcards(maybeAlteredType, !hasWildcardSuppressionAnnotation(vp), javaType)
694+
val typeWithWildcards = addJavaLoweringWildcards(maybeAlteredType, !getInnermostWildcardSupppressionAnnotation(vp), javaType)
695695
val substitutedType = typeSubstitution?.let { it(typeWithWildcards, TypeContext.OTHER, pluginContext) } ?: typeWithWildcards
696696
val id = useValueParameter(vp, parent)
697697
if (extractTypeAccess) {

java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -964,17 +964,24 @@ open class KotlinUsesExtractor(
964964
when {
965965
t.hasAnnotation(jvmWildcardAnnotation) -> true
966966
!addByDefault -> false
967-
t.hasAnnotation(jvmWildcardSuppressionAnnotation) -> false
968967
// If a Java declaration specifies a variance, introduce it even if it's pointless (e.g. ? extends FinalClass, or ? super Object)
969968
javaVariance == v -> true
970969
v == Variance.IN_VARIANCE -> !(t.isNullableAny() || t.isAny())
971970
v == Variance.OUT_VARIANCE -> extendsAdditionAllowed(t)
972971
else -> false
973972
}
974973

974+
// Returns true if `t` has `@JvmSuppressWildcards` or `@JvmSuppressWildcards(true)`,
975+
// false if it has `@JvmSuppressWildcards(false)`,
976+
// and null if the annotation is not present.
977+
@Suppress("UNCHECKED_CAST")
978+
private fun getWildcardSuppressionDirective(t: IrAnnotationContainer) =
979+
t.getAnnotation(jvmWildcardSuppressionAnnotation)?.let { (it.getValueArgument(0) as? IrConst<Boolean>)?.value ?: true }
980+
975981
private fun addJavaLoweringArgumentWildcards(p: IrTypeParameter, t: IrTypeArgument, addByDefault: Boolean, javaType: JavaType?): IrTypeArgument =
976982
(t as? IrTypeProjection)?.let {
977-
val newBase = addJavaLoweringWildcards(it.type, addByDefault, javaType)
983+
val newAddByDefault = getWildcardSuppressionDirective(it.type)?.not() ?: addByDefault
984+
val newBase = addJavaLoweringWildcards(it.type, newAddByDefault, javaType)
978985
// Note javaVariance == null means we don't have a Java type to conform to -- for example if this is a Kotlin source definition.
979986
val javaVariance = javaType?.let { jType ->
980987
when (jType) {
@@ -989,7 +996,7 @@ open class KotlinUsesExtractor(
989996
// For example, Java might declare f(Comparable<CharSequence> cs), in which case we shouldn't add a `? super ...`
990997
// wildcard. Note if javaType is unknown (e.g. this is a Kotlin source element), we assume wildcards should be added.
991998
(javaVariance == null || javaVariance == p.variance) &&
992-
wildcardAdditionAllowed(p.variance, it.type, addByDefault, javaVariance))
999+
wildcardAdditionAllowed(p.variance, it.type, newAddByDefault, javaVariance))
9931000
p.variance
9941001
else
9951002
it.variance
@@ -1008,12 +1015,13 @@ open class KotlinUsesExtractor(
10081015

10091016
fun addJavaLoweringWildcards(t: IrType, addByDefault: Boolean, javaType: JavaType?): IrType =
10101017
(t as? IrSimpleType)?.let {
1018+
val newAddByDefault = getWildcardSuppressionDirective(t)?.not() ?: addByDefault
10111019
val typeParams = it.classOrNull?.owner?.typeParameters ?: return t
10121020
val newArgs = typeParams.zip(it.arguments).mapIndexed { idx, pair ->
10131021
addJavaLoweringArgumentWildcards(
10141022
pair.first,
10151023
pair.second,
1016-
addByDefault,
1024+
newAddByDefault,
10171025
javaType?.let { jt -> getJavaTypeArgument(jt, idx) }
10181026
)
10191027
}
@@ -1061,7 +1069,7 @@ open class KotlinUsesExtractor(
10611069
classTypeArgsIncludingOuterClasses,
10621070
overridesCollectionsMethodWithAlteredParameterTypes(f),
10631071
getJavaCallable(f),
1064-
!hasWildcardSuppressionAnnotation(f)
1072+
!getInnermostWildcardSupppressionAnnotation(f)
10651073
)
10661074

10671075
/*
@@ -1220,10 +1228,11 @@ open class KotlinUsesExtractor(
12201228
else -> null
12211229
}
12221230

1223-
fun hasWildcardSuppressionAnnotation(d: IrDeclaration) =
1224-
d.hasAnnotation(jvmWildcardSuppressionAnnotation) ||
1231+
fun getInnermostWildcardSupppressionAnnotation(d: IrDeclaration) =
1232+
getWildcardSuppressionDirective(d) ?:
12251233
// Note not using `parentsWithSelf` as that only works if `d` is an IrDeclarationParent
1226-
d.parents.any { (it as? IrAnnotationContainer)?.hasAnnotation(jvmWildcardSuppressionAnnotation) == true }
1234+
d.parents.filterIsInstance<IrAnnotationContainer>().mapNotNull { getWildcardSuppressionDirective(it) }.firstOrNull() ?:
1235+
false
12271236

12281237
/**
12291238
* Class to hold labels for generated classes around local functions, lambdas, function references, and property references.

java/ql/integration-tests/all-platforms/kotlin/kotlin_java_lowering_wildcards/JavaUser.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public static void test() {
4949
KotlinDefnsSuppressedFn kdsf = new KotlinDefnsSuppressedFn();
5050
kdsf.outerFn((List<CharSequence>)null, (Comparable<CharSequence>)null);
5151

52+
kd.takesVariantTypesIndirectlySuppressedWildcards((List<CharSequence>)null, (Comparable<CharSequence>)null);
53+
kd.takesVariantTypesComplexSuppressionWildcards((List<List<? extends List<? extends CharSequence>>>)null);
54+
5255
}
5356

54-
}
57+
}

java/ql/integration-tests/all-platforms/kotlin/kotlin_java_lowering_wildcards/kotlindefns.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class KotlinDefns {
3333

3434
fun takesVariantTypesSuppressedWildcards(covar: List<@JvmSuppressWildcards CharSequence>, contravar: Comparable<@JvmSuppressWildcards CharSequence>) { }
3535

36+
fun takesVariantTypesIndirectlySuppressedWildcards(covar: @JvmSuppressWildcards List<CharSequence>, contravar: @JvmSuppressWildcards Comparable<CharSequence>) { }
37+
38+
fun takesVariantTypesComplexSuppressionWildcards(covar: @JvmSuppressWildcards(suppress = true) List<@JvmSuppressWildcards List<@JvmSuppressWildcards(suppress = false) List<CharSequence>>>) { }
39+
3640
fun returnsInvar() : MutableList<CharSequence> = mutableListOf()
3741

3842
fun returnsCovar(): List<CharSequence> = listOf()
@@ -75,4 +79,4 @@ class KotlinDefnsSuppressedFn {
7579

7680
@JvmSuppressWildcards fun outerFn(covar: List<CharSequence>, contravar: Comparable<CharSequence>) { }
7781

78-
}
82+
}

java/ql/integration-tests/all-platforms/kotlin/kotlin_java_lowering_wildcards/test.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
| KotlinDefns | takesNestedType | invar | List<List<CharSequence>> |
4141
| KotlinDefns | takesNestedType | mixed1 | List<? extends Comparable<? super CharSequence>> |
4242
| KotlinDefns | takesNestedType | mixed2 | Comparable<? super List<? extends CharSequence>> |
43+
| KotlinDefns | takesVariantTypesComplexSuppressionWildcards | covar | List<List<? extends List<? extends CharSequence>>> |
44+
| KotlinDefns | takesVariantTypesIndirectlySuppressedWildcards | contravar | Comparable<CharSequence> |
45+
| KotlinDefns | takesVariantTypesIndirectlySuppressedWildcards | covar | List<CharSequence> |
4346
| KotlinDefns | takesVariantTypesSuppressedWildcards | contravar | Comparable<CharSequence> |
4447
| KotlinDefns | takesVariantTypesSuppressedWildcards | covar | List<CharSequence> |
4548
| KotlinDefnsSuppressedFn | outerFn | contravar | Comparable<CharSequence> |

0 commit comments

Comments
 (0)