FIR: use frontend-independent Java type qualifier computation

This commit is contained in:
pyos
2021-08-11 21:20:15 +02:00
committed by teamcityserver
parent e385484994
commit e2a48d3945
14 changed files with 149 additions and 249 deletions
@@ -1,148 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.JavaDefaultQualifiers
import org.jetbrains.kotlin.load.java.typeEnhancement.*
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class EnhancementSignatureParts(
private val typeQualifierResolver: FirAnnotationTypeQualifierResolver,
private val typeContainer: FirAnnotationContainer?,
private val javaTypeParameterStack: JavaTypeParameterStack,
private val current: FirJavaTypeRef,
private val fromOverridden: Collection<FirTypeRef>,
private val isCovariant: Boolean,
private val context: FirJavaEnhancementContext,
private val containerApplicabilityType: AnnotationQualifierApplicabilityType
) {
private val isForVarargParameter get() = typeContainer.safeAs<FirValueParameter>()?.isVararg == true
private fun ConeKotlinType.toFqNameUnsafe(): FqNameUnsafe? =
((this as? ConeLookupTagBasedType)?.lookupTag as? ConeClassLikeLookupTag)?.classId?.asSingleFqName()?.toUnsafe()
internal fun enhance(
session: FirSession,
predefined: TypeEnhancementInfo? = null,
forAnnotationMember: Boolean = false
): FirResolvedTypeRef {
val mode = if (forAnnotationMember) FirJavaTypeConversionMode.ANNOTATION_MEMBER else FirJavaTypeConversionMode.DEFAULT
val typeWithoutEnhancement = current.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack, mode)
val qualifiers = computeIndexedQualifiersForOverride(typeWithoutEnhancement, predefined)
return buildResolvedTypeRef {
type = typeWithoutEnhancement.enhance(session, qualifiers) ?: typeWithoutEnhancement
annotations += current.annotations
}
}
private fun ConeKotlinType?.toIndexed(context: FirJavaEnhancementContext): List<TypeAndDefaultQualifiers> {
val list = ArrayList<TypeAndDefaultQualifiers>(1)
fun add(type: ConeKotlinType?) {
// TODO: should use the context from parent type
val annotations = type?.attributes?.customAnnotations.orEmpty()
val c = context.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, annotations)
list.add(TypeAndDefaultQualifiers(type, c.defaultTypeQualifiers?.get(AnnotationQualifierApplicabilityType.TYPE_USE)))
type?.typeArguments?.forEach { add(it.type) }
}
add(this)
return list
}
private fun ConeKotlinType.extractQualifiers(): JavaTypeQualifiers {
val lower = lowerBoundIfFlexible()
val upper = upperBoundIfFlexible()
val mapping = JavaToKotlinClassMap
return JavaTypeQualifiers(
when {
lower.isMarkedNullable -> NullabilityQualifier.NULLABLE
!upper.isMarkedNullable -> NullabilityQualifier.NOT_NULL
else -> null
},
when {
mapping.isReadOnly(lower.toFqNameUnsafe()) -> MutabilityQualifier.READ_ONLY
mapping.isMutable(upper.toFqNameUnsafe()) -> MutabilityQualifier.MUTABLE
else -> null
},
isNotNullTypeParameter = lower is ConeDefinitelyNotNullType
)
}
private fun composeAnnotations(first: List<FirAnnotationCall>, second: List<FirAnnotationCall>): List<FirAnnotationCall> {
return when {
first.isEmpty() -> second
second.isEmpty() -> first
else -> first + second
}
}
private fun TypeAndDefaultQualifiers.extractQualifiersFromAnnotations(isHeadTypeConstructor: Boolean): JavaTypeQualifiers {
val annotations = type?.attributes?.customAnnotations.orEmpty()
val composedAnnotations =
if (isHeadTypeConstructor && typeContainer != null)
composeAnnotations(typeContainer.annotations, annotations)
else
annotations
val defaultTypeQualifier =
if (isHeadTypeConstructor)
context.defaultTypeQualifiers?.get(containerApplicabilityType)
else
defaultQualifiers
val nullabilityInfo = typeQualifierResolver.extractNullability(composedAnnotations)
?: defaultTypeQualifier?.nullabilityQualifier
return JavaTypeQualifiers(
nullabilityInfo?.qualifier,
typeQualifierResolver.extractMutability(composedAnnotations),
isNotNullTypeParameter = nullabilityInfo?.qualifier == NullabilityQualifier.NOT_NULL &&
type?.lowerBoundIfFlexible() is ConeTypeParameterType,
isNullabilityQualifierForWarning = nullabilityInfo?.isForWarningOnly == true
)
}
private fun computeIndexedQualifiersForOverride(current: ConeKotlinType?, predefined: TypeEnhancementInfo?): IndexedJavaTypeQualifiers {
val indexedFromSupertypes =
fromOverridden.map { it.toConeKotlinTypeProbablyFlexible(context.session, javaTypeParameterStack).toIndexed(context) }
val indexedThisType = current.toIndexed(context)
// The covariant case may be hard, e.g. in the superclass the return may be Super<T>, but in the subclass it may be Derived, which
// is declared to extend Super<T>, and propagating data here is highly non-trivial, so we only look at the head type constructor
// (outermost type), unless the type in the subclass is interchangeable with the all the types in superclasses:
// e.g. we have (Mutable)List<String!>! in the subclass and { List<String!>, (Mutable)List<String>! } from superclasses
// Note that `this` is flexible here, so it's equal to it's bounds
val onlyHeadTypeConstructor = isCovariant && fromOverridden.any { true /*equalTypes(it, this)*/ }
val treeSize = if (onlyHeadTypeConstructor) 1 else indexedThisType.size
val computedResult = Array(treeSize) { index ->
val qualifiers = indexedThisType[index].extractQualifiersFromAnnotations(index == 0)
val superQualifiers = indexedFromSupertypes.mapNotNull { it.getOrNull(index)?.type?.extractQualifiers() }
qualifiers.computeQualifiersForOverride(superQualifiers, index == 0 && isCovariant, index == 0 && isForVarargParameter)
}
return { index -> predefined?.map?.get(index) ?: computedResult.getOrNull(index) ?: JavaTypeQualifiers.NONE }
}
private data class TypeAndDefaultQualifiers(
val type: ConeKotlinType?, // null denotes '*' here
val defaultQualifiers: JavaDefaultQualifiers?
)
}
@@ -21,13 +21,17 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
import org.jetbrains.kotlin.load.java.typeEnhancement.*
@@ -35,6 +39,12 @@ import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.load.java.JavaTypeEnhancementState
import org.jetbrains.kotlin.load.java.JavaTypeQualifiersByElementType
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeParameterMarker
import org.jetbrains.kotlin.types.model.TypeSystemContext
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FirSignatureEnhancement(
@@ -170,7 +180,7 @@ class FirSignatureEnhancement(
}
return enhanceMethod(firMethod, original.callableId, name)
}
private fun enhanceMethod(
firMethod: FirFunction,
methodId: CallableId,
@@ -309,14 +319,16 @@ class FirSignatureEnhancement(
overriddenMembers: List<FirCallableDeclaration>,
memberContext: FirJavaEnhancementContext
): FirResolvedTypeRef {
return ownerFunction.partsForValueParameter(
return ownerFunction.enhanceValueParameter(
typeQualifierResolver,
overriddenMembers,
// TODO: check me
parameterContainer = ownerFunction,
methodContext = memberContext,
typeInSignature = TypeInSignature.Receiver
).enhance(session)
typeInSignature = TypeInSignature.Receiver,
predefined = null,
forAnnotationMember = false
)
}
private fun enhanceValueParameterType(
@@ -331,15 +343,13 @@ class FirSignatureEnhancement(
if (ownerParameter.returnTypeRef is FirResolvedTypeRef) {
return ownerParameter.returnTypeRef as FirResolvedTypeRef
}
return ownerFunction.partsForValueParameter(
return ownerFunction.enhanceValueParameter(
typeQualifierResolver,
overriddenMembers,
parameterContainer = ownerParameter,
methodContext = memberContext,
typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index)
).enhance(
session,
predefinedEnhancementInfo?.parametersInfo?.getOrNull(index),
typeInSignature = TypeInSignature.ValueParameter(hasReceiver, index),
predefined = predefinedEnhancementInfo?.parametersInfo?.getOrNull(index),
forAnnotationMember = owner.classKind == ClassKind.ANNOTATION_CLASS
)
}
@@ -350,7 +360,7 @@ class FirSignatureEnhancement(
memberContext: FirJavaEnhancementContext,
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?
): FirResolvedTypeRef {
return owner.parts(
return owner.enhance(
typeQualifierResolver,
overriddenMembers,
typeContainer = owner, isCovariant = true,
@@ -358,9 +368,9 @@ class FirSignatureEnhancement(
containerApplicabilityType =
if (owner is FirJavaField) AnnotationQualifierApplicabilityType.FIELD
else AnnotationQualifierApplicabilityType.METHOD_RETURN_TYPE,
typeInSignature = TypeInSignature.Return
).enhance(
session, predefinedEnhancementInfo?.returnTypeInfo, forAnnotationMember = this.owner.classKind == ClassKind.ANNOTATION_CLASS
typeInSignature = TypeInSignature.Return,
predefined = predefinedEnhancementInfo?.returnTypeInfo,
forAnnotationMember = this.owner.classKind == ClassKind.ANNOTATION_CLASS
)
}
@@ -388,14 +398,16 @@ class FirSignatureEnhancement(
}
}
private fun FirFunction.partsForValueParameter(
private fun FirFunction.enhanceValueParameter(
typeQualifierResolver: FirAnnotationTypeQualifierResolver,
overriddenMembers: List<FirCallableDeclaration>,
// TODO: investigate if it's really can be a null (check properties' with extension overrides in Java)
parameterContainer: FirAnnotationContainer?,
methodContext: FirJavaEnhancementContext,
typeInSignature: TypeInSignature
): EnhancementSignatureParts = (this as FirCallableDeclaration).parts(
typeInSignature: TypeInSignature,
predefined: TypeEnhancementInfo?,
forAnnotationMember: Boolean
): FirResolvedTypeRef = (this as FirCallableDeclaration).enhance(
typeQualifierResolver,
overriddenMembers,
parameterContainer, false,
@@ -403,33 +415,79 @@ class FirSignatureEnhancement(
methodContext.copyWithNewDefaultTypeQualifiers(typeQualifierResolver, it.annotations)
} ?: methodContext,
AnnotationQualifierApplicabilityType.VALUE_PARAMETER,
typeInSignature
typeInSignature,
predefined,
forAnnotationMember
)
private fun FirCallableDeclaration.parts(
private fun FirCallableDeclaration.enhance(
typeQualifierResolver: FirAnnotationTypeQualifierResolver,
overriddenMembers: List<FirCallableDeclaration>,
typeContainer: FirAnnotationContainer?,
isCovariant: Boolean,
containerContext: FirJavaEnhancementContext,
containerApplicabilityType: AnnotationQualifierApplicabilityType,
typeInSignature: TypeInSignature
): EnhancementSignatureParts {
val typeRef = typeInSignature.getTypeRef(this)
return EnhancementSignatureParts(
typeQualifierResolver,
typeContainer,
javaTypeParameterStack,
typeRef as FirJavaTypeRef,
overriddenMembers.map {
typeInSignature.getTypeRef(it)
},
isCovariant,
// recompute default type qualifiers using type annotations
containerContext.copyWithNewDefaultTypeQualifiers(
typeQualifierResolver, typeRef.annotations
),
containerApplicabilityType
typeInSignature: TypeInSignature,
predefined: TypeEnhancementInfo?,
forAnnotationMember: Boolean
): FirResolvedTypeRef {
val parts = EnhancementSignatureParts(
session, typeQualifierResolver, typeContainer, isCovariant,
containerApplicabilityType, containerContext.defaultTypeQualifiers
)
val typeRef = typeInSignature.getTypeRef(this)
val mode = if (forAnnotationMember) FirJavaTypeConversionMode.ANNOTATION_MEMBER else FirJavaTypeConversionMode.DEFAULT
val typeWithoutEnhancement = typeRef.toConeKotlinType(mode)
val typesFromOverridden = overriddenMembers.map { typeInSignature.getTypeRef(it).toConeKotlinType(mode) }
val qualifiers = with(parts) { typeWithoutEnhancement.computeIndexedQualifiers(typesFromOverridden, predefined) }
return buildResolvedTypeRef {
type = typeWithoutEnhancement.enhance(session, qualifiers) ?: typeWithoutEnhancement
annotations += typeRef.annotations
}
}
private fun FirTypeRef.toConeKotlinType(mode: FirJavaTypeConversionMode): ConeKotlinType =
toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack, mode)
}
private class EnhancementSignatureParts(
private val session: FirSession,
override val annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver,
private val typeContainer: FirAnnotationContainer?,
override val isCovariant: Boolean,
override val containerApplicabilityType: AnnotationQualifierApplicabilityType,
override val containerDefaultTypeQualifiers: JavaTypeQualifiersByElementType?
) : AbstractSignatureParts<FirAnnotationCall>() {
override val enableImprovementsInStrictMode: Boolean
get() = true
override val skipRawTypeArguments: Boolean
get() = false
override val containerAnnotations: Iterable<FirAnnotationCall>
get() = typeContainer?.annotations ?: emptyList()
override val containerIsVarargParameter: Boolean
get() = typeContainer is FirValueParameter && typeContainer.isVararg
override val typeSystem: TypeSystemContext
get() = session.typeContext
override val FirAnnotationCall.forceWarning: Boolean
get() = false // TODO: force warnings on IDEA external annotations
override val KotlinTypeMarker.annotations: Iterable<FirAnnotationCall>
get() = (this as ConeKotlinType).attributes.customAnnotations
override val KotlinTypeMarker.fqNameUnsafe: FqNameUnsafe?
get() = ((this as? ConeLookupTagBasedType)?.lookupTag as? ConeClassLikeLookupTag)?.classId?.asSingleFqName()?.toUnsafe()
override val KotlinTypeMarker.enhancedForWarnings: KotlinTypeMarker?
get() = null // TODO: implement enhancement for warnings
override fun KotlinTypeMarker.isEqual(other: KotlinTypeMarker): Boolean =
AbstractTypeChecker.equalTypes(session.typeContext, this, other)
override val TypeParameterMarker.isFromJava: Boolean
get() = (this as ConeTypeParameterLookupTag).symbol.fir.origin == FirDeclarationOrigin.Java
}
@@ -34,8 +34,6 @@ import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.utils.extractRadix
typealias IndexedJavaTypeQualifiers = (Int) -> JavaTypeQualifiers
internal fun ConeKotlinType.enhance(session: FirSession, qualifiers: IndexedJavaTypeQualifiers): ConeKotlinType? =
enhanceConeKotlinType(session, qualifiers, 0, mutableListOf<Int>().apply { computeSubtreeSizes(this) })
@@ -15,23 +15,19 @@ public class Test {}
// FILE: main.kt
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<Any?>, x: Test): Unit {
// jspecify_nullness_mismatch
a1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
a1.foo(null)
a1.foo(1)
// jspecify_nullness_mismatch
a2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
a2.foo(null)
a2.foo(1)
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
// jspecify_nullness_mismatch
a1.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
a1.bar(x, null)
a1.bar(x, 1)
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
// jspecify_nullness_mismatch
a2.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
a2.bar(x, null)
a2.bar(x, 1)
}
@@ -39,15 +39,12 @@ public class CKN extends C<@Nullable CK> {}
// FILE: main.kt
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
ak.foo(ak)
// jspecify_nullness_mismatch
ak.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
ak.foo(null)
// jspecify_nullness_mismatch
akn.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
akn.foo(null)
bk.foo(bk)
// jspecify_nullness_mismatch
bk.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
bk.foo(null)
ck.foo(ck)
ck.foo(null)
@@ -30,13 +30,11 @@ fun <T : Test> main(a1: A<Any?>, a2: A<Test>, b1: B<Any?>, b2: B<Test>, x: T): U
a2.bar<T?>(null)
a2.bar<T>(x)
// jspecify_nullness_mismatch
b1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
b1.foo(null)
b1.bar<T?>(null)
b1.bar<T>(x)
// jspecify_nullness_mismatch
b2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
b2.foo(null)
b2.bar<T?>(null)
b2.bar<T>(x)
}
@@ -14,5 +14,5 @@ public class Foo<T extends @Nullable Object> {
// FILE: main.kt
fun test(): Foo<String> {
return <!DEBUG_INFO_EXPRESSION_TYPE("Foo<kotlin.String>")!>Foo.create()<!>
return <!DEBUG_INFO_EXPRESSION_TYPE("Foo<kotlin.String..kotlin.String?!>")!>Foo.create()<!>
}
@@ -14,17 +14,17 @@ public class Test {}
// FILE: main.kt
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<Any?>, x: Test): Unit {
a1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
a1.foo(null)
a1.foo(1)
a2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
a2.foo(null)
a2.foo(1)
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a1.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a1.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
a1.bar(x, null)
a1.bar(x, 1)
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a2.bar(x, <!NULL_FOR_NONNULL_TYPE!>null<!>)
a2.bar(<!NULL_FOR_NONNULL_TYPE!>null<!>, null)
a2.bar(x, null)
a2.bar(x, 1)
}
@@ -40,12 +40,12 @@ public class CKN extends C<@Nullable CK> {}
// FILE: main.kt
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
ak.foo(ak)
ak.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
ak.foo(null)
akn.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>) // the corresponding warning/error is present on the Java side
akn.foo(null) // the corresponding warning/error is present on the Java side
bk.foo(bk)
bk.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
bk.foo(null)
ck.foo(ck)
ck.foo(null)
@@ -29,11 +29,11 @@ fun <T : Test> main(a1: A<Any?>, a2: A<Test>, b1: B<Any?>, b2: B<Test>, x: T): U
a2.bar<T?>(null)
a2.bar<T>(x)
b1.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
b1.foo(null)
b1.bar<T?>(null)
b1.bar<T>(x)
b2.foo(<!NULL_FOR_NONNULL_TYPE!>null<!>)
b2.foo(null)
b2.bar<T?>(null)
b2.bar<T>(x)
}
@@ -51,15 +51,15 @@ fun <R> main(a: ReturnType<R>) {
takeNotNullStringAndNotNullK(x3)
takeNullableStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x3<!>)
val x4 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<R!!>..kotlin.Array<out R!!>")!>a.foo4<!>
val x4 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<R!!>..kotlin.Array<out R!!>?!")!>a.foo4<!>
takeArrayOfNotNullString(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
takeArrayOfNullableString(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
takeArrayOfNotNullK(x4)
takeArrayOfNullableK(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
val x5 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<kotlin.String?>?..kotlin.Array<out kotlin.String?>??")!>a.foo5()<!>
val x5 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<kotlin.String?>..kotlin.Array<out kotlin.String?>?!")!>a.foo5()<!>
takeArrayOfNotNullString(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableString(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableString(x5)
takeArrayOfNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableK(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableK(x5)
}
@@ -53,15 +53,15 @@ fun <R> main(a: ReturnTypeWithWarnings<R>) {
takeNotNullStringAndNotNullK(x3)
takeNullableStringAndNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x3<!>)
val x4 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<R!!>..kotlin.Array<out R!!>")!>a.foo4<!>
val x4 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<R!!>..kotlin.Array<out R!!>?!")!>a.foo4<!>
takeArrayOfNotNullString(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
takeArrayOfNullableString(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
takeArrayOfNotNullK(x4)
takeArrayOfNullableK(<!ARGUMENT_TYPE_MISMATCH!>x4<!>)
val x5 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<kotlin.String?>?..kotlin.Array<out kotlin.String?>??")!>a.foo5()<!>
val x5 = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Array<kotlin.String?>..kotlin.Array<out kotlin.String?>?!")!>a.foo5()<!>
takeArrayOfNotNullString(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableString(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableString(x5)
takeArrayOfNotNullK(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableK(<!ARGUMENT_TYPE_MISMATCH!>x5<!>)
takeArrayOfNullableK(x5)
}
@@ -32,9 +32,9 @@ fun testDesugaredForInList() {
fun testForInArrayUnused(j: J) {
{ // BLOCK
val <iterator>: Iterator<@FlexibleNullability P?> = j.arrayOfNotNull().iterator()
val <iterator>: Iterator<@EnhancedNullability P> = j.arrayOfNotNull().iterator()
while (<iterator>.hasNext()) { // BLOCK
val x: @FlexibleNullability P? = <iterator>.next()
val x: P = <iterator>.next() /*!! P */
}
}
}
@@ -54,11 +54,11 @@ fun testForInListUse() {
fun testForInArrayUse(j: J) {
{ // BLOCK
val <iterator>: Iterator<@FlexibleNullability P?> = j.arrayOfNotNull().iterator()
val <iterator>: Iterator<@EnhancedNullability P> = j.arrayOfNotNull().iterator()
while (<iterator>.hasNext()) { // BLOCK
val x: @FlexibleNullability P? = <iterator>.next()
val x: P = <iterator>.next() /*!! P */
{ // BLOCK
use(s = x /*!! @FlexibleNullability P */)
use(s = x)
use(s = x)
}
}
@@ -54,17 +54,18 @@ FILE fqName:<root> fileName:/enhancedNullabilityInForLoop.kt
VALUE_PARAMETER name:j index:0 type:<root>.J
BLOCK_BODY
BLOCK type=kotlin.Unit origin=FOR_LOOP
VAR FOR_LOOP_ITERATOR name:tmp_2 type:kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val]
CALL 'public final fun iterator (): kotlin.collections.Iterator<T of kotlin.Array> [operator] declared in kotlin.Array' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
$this: CALL 'public open fun arrayOfNotNull (): @[EnhancedNullability] kotlin.Array<out @[FlexibleNullability] <root>.P?> declared in <root>.J' type=@[EnhancedNullability] kotlin.Array<out @[FlexibleNullability] <root>.P?> origin=null
VAR FOR_LOOP_ITERATOR name:tmp_2 type:kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val]
CALL 'public final fun iterator (): kotlin.collections.Iterator<T of kotlin.Array> [operator] declared in kotlin.Array' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
$this: CALL 'public open fun arrayOfNotNull (): @[EnhancedNullability] kotlin.Array<out @[EnhancedNullability] <root>.P> declared in <root>.J' type=@[EnhancedNullability] kotlin.Array<out @[EnhancedNullability] <root>.P> origin=null
$this: GET_VAR 'j: <root>.J declared in <root>.testForInArrayUnused' type=<root>.J origin=null
WHILE label=null origin=FOR_LOOP_INNER_WHILE
condition: CALL 'public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=FOR_LOOP_HAS_NEXT
$this: GET_VAR 'val tmp_2: kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val] declared in <root>.testForInArrayUnused' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
$this: GET_VAR 'val tmp_2: kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val] declared in <root>.testForInArrayUnused' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
body: BLOCK type=kotlin.Unit origin=FOR_LOOP_INNER_WHILE
VAR FOR_LOOP_VARIABLE name:x type:@[FlexibleNullability] <root>.P? [val]
CALL 'public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator' type=@[FlexibleNullability] <root>.P? origin=FOR_LOOP_NEXT
$this: GET_VAR 'val tmp_2: kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val] declared in <root>.testForInArrayUnused' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
VAR FOR_LOOP_VARIABLE name:x type:<root>.P [val]
TYPE_OP type=<root>.P origin=IMPLICIT_NOTNULL typeOperand=<root>.P
CALL 'public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator' type=@[EnhancedNullability] <root>.P origin=FOR_LOOP_NEXT
$this: GET_VAR 'val tmp_2: kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val] declared in <root>.testForInArrayUnused' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
FUN name:testForInListUse visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
BLOCK type=kotlin.Unit origin=FOR_LOOP
@@ -88,23 +89,23 @@ FILE fqName:<root> fileName:/enhancedNullabilityInForLoop.kt
VALUE_PARAMETER name:j index:0 type:<root>.J
BLOCK_BODY
BLOCK type=kotlin.Unit origin=FOR_LOOP
VAR FOR_LOOP_ITERATOR name:tmp_4 type:kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val]
CALL 'public final fun iterator (): kotlin.collections.Iterator<T of kotlin.Array> [operator] declared in kotlin.Array' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
$this: CALL 'public open fun arrayOfNotNull (): @[EnhancedNullability] kotlin.Array<out @[FlexibleNullability] <root>.P?> declared in <root>.J' type=@[EnhancedNullability] kotlin.Array<out @[FlexibleNullability] <root>.P?> origin=null
VAR FOR_LOOP_ITERATOR name:tmp_4 type:kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val]
CALL 'public final fun iterator (): kotlin.collections.Iterator<T of kotlin.Array> [operator] declared in kotlin.Array' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
$this: CALL 'public open fun arrayOfNotNull (): @[EnhancedNullability] kotlin.Array<out @[EnhancedNullability] <root>.P> declared in <root>.J' type=@[EnhancedNullability] kotlin.Array<out @[EnhancedNullability] <root>.P> origin=null
$this: GET_VAR 'j: <root>.J declared in <root>.testForInArrayUse' type=<root>.J origin=null
WHILE label=null origin=FOR_LOOP_INNER_WHILE
condition: CALL 'public abstract fun hasNext (): kotlin.Boolean [operator] declared in kotlin.collections.Iterator' type=kotlin.Boolean origin=FOR_LOOP_HAS_NEXT
$this: GET_VAR 'val tmp_4: kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val] declared in <root>.testForInArrayUse' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
$this: GET_VAR 'val tmp_4: kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val] declared in <root>.testForInArrayUse' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
body: BLOCK type=kotlin.Unit origin=FOR_LOOP_INNER_WHILE
VAR FOR_LOOP_VARIABLE name:x type:@[FlexibleNullability] <root>.P? [val]
CALL 'public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator' type=@[FlexibleNullability] <root>.P? origin=FOR_LOOP_NEXT
$this: GET_VAR 'val tmp_4: kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> [val] declared in <root>.testForInArrayUse' type=kotlin.collections.Iterator<@[FlexibleNullability] <root>.P?> origin=null
VAR FOR_LOOP_VARIABLE name:x type:<root>.P [val]
TYPE_OP type=<root>.P origin=IMPLICIT_NOTNULL typeOperand=<root>.P
CALL 'public abstract fun next (): T of kotlin.collections.Iterator [operator] declared in kotlin.collections.Iterator' type=@[EnhancedNullability] <root>.P origin=FOR_LOOP_NEXT
$this: GET_VAR 'val tmp_4: kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> [val] declared in <root>.testForInArrayUse' type=kotlin.collections.Iterator<@[EnhancedNullability] <root>.P> origin=null
BLOCK type=kotlin.Unit origin=null
CALL 'public final fun use (s: <root>.P): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
s: TYPE_OP type=@[FlexibleNullability] <root>.P origin=IMPLICIT_NOTNULL typeOperand=@[FlexibleNullability] <root>.P
GET_VAR 'val x: @[FlexibleNullability] <root>.P? [val] declared in <root>.testForInArrayUse' type=@[FlexibleNullability] <root>.P? origin=null
s: GET_VAR 'val x: <root>.P [val] declared in <root>.testForInArrayUse' type=<root>.P origin=null
CALL 'public open fun use (s: @[EnhancedNullability] <root>.P): kotlin.Unit declared in <root>.J' type=kotlin.Unit origin=null
s: GET_VAR 'val x: @[FlexibleNullability] <root>.P? [val] declared in <root>.testForInArrayUse' type=@[FlexibleNullability] <root>.P? origin=null
s: GET_VAR 'val x: <root>.P [val] declared in <root>.testForInArrayUse' type=<root>.P origin=null
CLASS INTERFACE name:K modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.K
FUN name:arrayOfNotNull visibility:public modality:ABSTRACT <> ($this:<root>.K) returnType:kotlin.Array<<root>.P>