[FIR] Don't approximate captured types

This fixes some type argument mismatch errors caused by a captured type
being approximated and then captured again.
Some places need to be adapted to work with captured types that
previously only worked with approximated types.

#KT-62959 Fixed
This commit is contained in:
Kirill Rakhman
2023-12-20 11:10:25 +01:00
committed by Space Team
parent b6d7f35ebf
commit 251827c9aa
58 changed files with 506 additions and 86 deletions
@@ -17917,6 +17917,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt");
}
@Test
@TestMetadata("capturingOfDnn.kt")
public void testCapturingOfDnn() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingOfDnn.kt");
}
@Test
@TestMetadata("differentCapturedTypes.kt")
public void testDifferentCapturedTypes() throws Exception {
@@ -33742,6 +33748,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
}
@Test
@TestMetadata("ExhaustiveOnCaptured.kt")
public void testExhaustiveOnCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveOnCaptured.kt");
}
@Test
@TestMetadata("ExhaustiveOnRoot.kt")
public void testExhaustiveOnRoot() throws Exception {
@@ -3525,6 +3525,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag
runTest("compiler/fir/analysis-tests/testData/resolve/inference/nullableIntegerLiteralType.kt");
}
@Test
@TestMetadata("onlyInputTypesCapturedTypeWithRecursiveBounds.kt")
public void testOnlyInputTypesCapturedTypeWithRecursiveBounds() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/onlyInputTypesCapturedTypeWithRecursiveBounds.kt");
}
@Test
@TestMetadata("overloadResolutionByLambdaArgumentType.kt")
public void testOverloadResolutionByLambdaArgumentType() throws Exception {
@@ -17917,6 +17917,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt");
}
@Test
@TestMetadata("capturingOfDnn.kt")
public void testCapturingOfDnn() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingOfDnn.kt");
}
@Test
@TestMetadata("differentCapturedTypes.kt")
public void testDifferentCapturedTypes() throws Exception {
@@ -33742,6 +33748,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
}
@Test
@TestMetadata("ExhaustiveOnCaptured.kt")
public void testExhaustiveOnCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveOnCaptured.kt");
}
@Test
@TestMetadata("ExhaustiveOnRoot.kt")
public void testExhaustiveOnRoot() throws Exception {
@@ -3525,6 +3525,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated
runTest("compiler/fir/analysis-tests/testData/resolve/inference/nullableIntegerLiteralType.kt");
}
@Test
@TestMetadata("onlyInputTypesCapturedTypeWithRecursiveBounds.kt")
public void testOnlyInputTypesCapturedTypeWithRecursiveBounds() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/onlyInputTypesCapturedTypeWithRecursiveBounds.kt");
}
@Test
@TestMetadata("overloadResolutionByLambdaArgumentType.kt")
public void testOverloadResolutionByLambdaArgumentType() throws Exception {
@@ -6,7 +6,7 @@ val <U> KClass<U>.javaImpl: Class<U>
get() = null!!
val <T : KClass<*>> T.myJava1: Class<*>
get() = <!DEBUG_INFO_EXPRESSION_TYPE("java.lang.Class<out kotlin.Any>")!>javaImpl<!>
get() = <!DEBUG_INFO_EXPRESSION_TYPE("java.lang.Class<CapturedType(*)>")!>javaImpl<!>
val <E : Any, T : KClass<E>> T.myJava2: Class<E>
get() = <!DEBUG_INFO_EXPRESSION_TYPE("java.lang.Class<E>")!>javaImpl<!>
@@ -0,0 +1,75 @@
FILE: onlyInputTypesCapturedTypeWithRecursiveBounds.kt
public abstract interface I : R|kotlin/Any| {
}
public final enum class MyEnum : R|I|, R|kotlin/Enum<MyEnum>| {
private constructor(): R|MyEnum| {
super<R|kotlin/Enum<MyEnum>|>()
}
public final static enum entry EnumEntry: R|MyEnum|
public final static fun values(): R|kotlin/Array<MyEnum>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|MyEnum| {
}
public final static val entries: R|kotlin/enums/EnumEntries<MyEnum>|
public get(): R|kotlin/enums/EnumEntries<MyEnum>|
}
public open class Foo<P : R|kotlin/Enum<P>|, R|I|> : R|kotlin/Any| {
public constructor<P : R|kotlin/Enum<P>|, R|I|>(data: R|kotlin/collections/Map<P, kotlin/Any?>|): R|Foo<P>| {
super<R|kotlin/Any|>()
}
public final val data: R|kotlin/collections/Map<P, kotlin/Any?>| = R|<local>/data|
public get(): R|kotlin/collections/Map<P, kotlin/Any?>|
}
private final fun test(node: R|Foo<*>|): R|kotlin/Unit| {
R|<local>/node|.R|SubstitutionOverride</Foo.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|it(kotlin/Enum<*> & I)|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
}
public open class FooEnumMap<P : R|kotlin/Enum<P>|, R|I|> : R|kotlin/Any| {
public constructor<P : R|kotlin/Enum<P>|, R|I|>(data: R|java/util/EnumMap<P, kotlin/Any?>|): R|FooEnumMap<P>| {
super<R|kotlin/Any|>()
}
public final val data: R|java/util/EnumMap<P, kotlin/Any?>| = R|<local>/data|
public get(): R|java/util/EnumMap<P, kotlin/Any?>|
}
private final fun test(node: R|FooEnumMap<*>|): R|kotlin/Unit| {
R|<local>/node|.R|SubstitutionOverride</FooEnumMap.data: R|java/util/EnumMap<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|ft<it(kotlin/Enum<*> & I), it(kotlin/Enum<*>? & I?)>|, R|kotlin/Any!|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
}
public open class Foo2<P : R|I|> : R|kotlin/Any| {
public constructor<P : R|I|>(data: R|kotlin/collections/Map<P, kotlin/Any?>|): R|Foo2<P>| {
super<R|kotlin/Any|>()
}
public final val data: R|kotlin/collections/Map<P, kotlin/Any?>| = R|<local>/data|
public get(): R|kotlin/collections/Map<P, kotlin/Any?>|
}
private final fun test(node: R|Foo2<*>|): R|kotlin/Unit| {
R|<local>/node|.R|SubstitutionOverride</Foo2.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|I|, R|kotlin/Any?|>(Q|MyEnum|.R|/MyEnum.EnumEntry|)
}
public abstract interface I2 : R|kotlin/Any| {
}
public final object C : R|I|, R|I2| {
private constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public open class Foo3<P : R|I|, R|I2|> : R|kotlin/Any| {
public constructor<P : R|I|, R|I2|>(data: R|kotlin/collections/Map<P, kotlin/Any?>|): R|Foo3<P>| {
super<R|kotlin/Any|>()
}
public final val data: R|kotlin/collections/Map<P, kotlin/Any?>| = R|<local>/data|
public get(): R|kotlin/collections/Map<P, kotlin/Any?>|
}
public final fun test3(node: R|Foo3<*>|): R|kotlin/Unit| {
R|<local>/node|.R|SubstitutionOverride</Foo3.data: R|kotlin/collections/Map<CapturedType(*), kotlin/Any?>|>|.R|kotlin/collections/get|<R|it(I & I2)|, R|kotlin/Any?|>(Q|C|)
}
@@ -0,0 +1,37 @@
// FULL_JDK
// WITH_STDLIB
import java.util.EnumMap
interface I
enum class MyEnum : I {
EnumEntry
}
open class Foo<P>(val data: Map<P, Any?>) where P : Enum<P>, P : I
private fun test(node: Foo<*>) {
node.data.get(MyEnum.EnumEntry)
}
open class FooEnumMap<P>(val data: EnumMap<P, Any?>) where P : Enum<P>, P : I
private fun test(node: FooEnumMap<*>) {
node.data.get(MyEnum.EnumEntry)
}
open class Foo2<P : I>(val data: Map<P, Any?>)
private fun test(node: Foo2<*>) {
node.data.get(MyEnum.EnumEntry)
}
interface I2
object C: I, I2
open class Foo3<P>(val data: Map<P, Any?>) where P : I, P : I2
fun test3(node: Foo3<*>) {
node.data.get(C)
}
@@ -15,7 +15,7 @@ public interface Option<T> {
// FILE: test.kt
fun test_1(option: Option<Pair<String, String>>?) {
if (option is Option.Some<*>) {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Pair<kotlin.String, kotlin.String>..kotlin.Pair<kotlin.String, kotlin.String>?!")!>option.get()<!>.first
val x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)!! & kotlin.Pair<kotlin.String, kotlin.String>..CapturedType(*)? & kotlin.Pair<kotlin.String, kotlin.String>?")!>option.get()<!>.first
x.length
}
}
@@ -3525,6 +3525,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi
runTest("compiler/fir/analysis-tests/testData/resolve/inference/nullableIntegerLiteralType.kt");
}
@Test
@TestMetadata("onlyInputTypesCapturedTypeWithRecursiveBounds.kt")
public void testOnlyInputTypesCapturedTypeWithRecursiveBounds() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/onlyInputTypesCapturedTypeWithRecursiveBounds.kt");
}
@Test
@TestMetadata("overloadResolutionByLambdaArgumentType.kt")
public void testOverloadResolutionByLambdaArgumentType() throws Exception {
@@ -17911,6 +17911,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt");
}
@Test
@TestMetadata("capturingOfDnn.kt")
public void testCapturingOfDnn() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingOfDnn.kt");
}
@Test
@TestMetadata("differentCapturedTypes.kt")
public void testDifferentCapturedTypes() throws Exception {
@@ -31456,6 +31462,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
}
@Test
@TestMetadata("ExhaustiveOnCaptured.kt")
public void testExhaustiveOnCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveOnCaptured.kt");
}
@Test
@TestMetadata("ExhaustiveOnRoot.kt")
public void testExhaustiveOnRoot() throws Exception {
@@ -3525,6 +3525,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest
runTest("compiler/fir/analysis-tests/testData/resolve/inference/nullableIntegerLiteralType.kt");
}
@Test
@TestMetadata("onlyInputTypesCapturedTypeWithRecursiveBounds.kt")
public void testOnlyInputTypesCapturedTypeWithRecursiveBounds() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/inference/onlyInputTypesCapturedTypeWithRecursiveBounds.kt");
}
@Test
@TestMetadata("overloadResolutionByLambdaArgumentType.kt")
public void testOverloadResolutionByLambdaArgumentType() throws Exception {
@@ -17917,6 +17917,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt");
}
@Test
@TestMetadata("capturingOfDnn.kt")
public void testCapturingOfDnn() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingOfDnn.kt");
}
@Test
@TestMetadata("differentCapturedTypes.kt")
public void testDifferentCapturedTypes() throws Exception {
@@ -31576,6 +31582,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
}
@Test
@TestMetadata("ExhaustiveOnCaptured.kt")
public void testExhaustiveOnCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveOnCaptured.kt");
}
@Test
@TestMetadata("ExhaustiveOnRoot.kt")
public void testExhaustiveOnRoot() throws Exception {
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
import org.jetbrains.kotlin.resolve.AnnotationTargetList
import org.jetbrains.kotlin.resolve.AnnotationTargetLists
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
import org.jetbrains.kotlin.util.ImplementationStatus
@@ -816,6 +817,13 @@ fun ConeKotlinType.hasDiagnosticKind(kind: DiagnosticKind): Boolean {
return this is ConeErrorType && (diagnostic as? ConeSimpleDiagnostic)?.kind == kind
}
fun ConeKotlinType.finalApproximationOrSelf(context: CheckerContext): ConeKotlinType {
return context.session.typeApproximator.approximateToSuperType(
this,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
) ?: this
}
fun FirResolvedQualifier.isStandalone(
context: CheckerContext,
): Boolean {
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.CastingType
import org.jetbrains.kotlin.fir.analysis.checkers.checkCasting
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.finalApproximationOrSelf
import org.jetbrains.kotlin.fir.analysis.checkers.isCastErased
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirOperation
@@ -24,9 +25,9 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker() {
override fun check(expression: FirTypeOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) {
val session = context.session
val firstArgument = expression.argumentList.arguments[0]
val actualType = firstArgument.unwrapSmartcastExpression().resolvedType.fullyExpandedType(session)
val actualType = firstArgument.unwrapSmartcastExpression().resolvedType.fullyExpandedType(session).finalApproximationOrSelf(context)
val conversionTypeRef = expression.conversionTypeRef
val targetType = conversionTypeRef.coneType.fullyExpandedType(session)
val targetType = conversionTypeRef.coneType.fullyExpandedType(session).finalApproximationOrSelf(context)
if (expression.operation in FirOperation.TYPES && targetType is ConeDynamicType) {
reporter.reportOn(conversionTypeRef.source, FirErrors.DYNAMIC_NOT_ALLOWED, context)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.collectUpperBounds
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.finalApproximationOrSelf
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
@@ -383,7 +384,10 @@ private val FirExpression.mostOriginalTypeIfSmartCast: ConeKotlinType
private fun FirExpression.toArgumentInfo(context: CheckerContext) =
ArgumentInfo(
this, resolvedType, mostOriginalTypeIfSmartCast.fullyExpandedType(context.session), context.session,
this,
userType = resolvedType.finalApproximationOrSelf(context),
originalType = mostOriginalTypeIfSmartCast.fullyExpandedType(context.session).finalApproximationOrSelf(context),
context.session,
)
/**
@@ -24,9 +24,11 @@ val FirComparisonExpression.left: FirExpression
val FirComparisonExpression.right: FirExpression
get() = compareToCall.arguments.getOrNull(0) ?: error("There should be a first arg for ${compareToCall.render()}")
context(Fir2IrComponents)
fun FirComparisonExpression.inferPrimitiveNumericComparisonInfo(): PrimitiveConeNumericComparisonInfo? =
inferPrimitiveNumericComparisonInfo(left, right)
context(Fir2IrComponents)
fun inferPrimitiveNumericComparisonInfo(left: FirExpression, right: FirExpression): PrimitiveConeNumericComparisonInfo? {
val leftType = left.resolvedType
val rightType = right.resolvedType
@@ -57,6 +59,7 @@ private fun ConeClassLikeType.promoteIntegerTypeToIntIfRequired(): ConeClassLike
else -> error("Primitive number type expected: $this")
}
context(Fir2IrComponents)
private fun ConeKotlinType.getPrimitiveTypeOrSupertype(): ConeClassLikeType? =
when {
this is ConeTypeParameterType ->
@@ -67,6 +70,8 @@ private fun ConeKotlinType.getPrimitiveTypeOrSupertype(): ConeClassLikeType? =
this
this is ConeFlexibleType ->
this.lowerBound.getPrimitiveTypeOrSupertype()
this is ConeCapturedType ->
this.approximateForIrOrSelf().getPrimitiveTypeOrSupertype()
else ->
null
}
@@ -343,6 +343,13 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return isProjectionNotNull
}
override fun CapturedTypeMarker.hasRawSuperType(): Boolean {
require(this is ConeCapturedType)
return constructor.supertypes?.any { superType ->
superType.contains { it is ConeKotlinType && it.isRaw() }
} == true
}
override fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker {
require(this is ConeDefinitelyNotNullType)
return this.original
@@ -425,8 +425,26 @@ fun ConeTypeContext.captureArguments(type: ConeKotlinType, status: CaptureStatus
}
require(newArgument is ConeCapturedType)
@Suppress("UNCHECKED_CAST")
newArgument.constructor.supertypes = upperBounds as List<ConeKotlinType>
newArgument.constructor.supertypes = if (status == CaptureStatus.FROM_EXPRESSION) {
// By intersecting the bounds and the projection type, we eliminate "redundant" super types.
// Redundant is defined by the implementation of the type intersector,
// e.g., at the moment of writing the intersection of Foo<String!> and Foo<String> was Foo<String>.
// Note, it's not just an optimization, but actually influences behavior because the nullability can change like in the
// example above.
// We only run it for status == CaptureStatus.FROM_EXPRESSION to prevent infinite loops with recursive types because
// during intersection AbstractTypeChecker is called which in turn can capture super types with status
// CaptureStatus.FOR_SUBTYPING.
val intersectedUpperBounds = intersectTypes(upperBounds)
if (intersectedUpperBounds is ConeIntersectionType) {
intersectedUpperBounds.intersectedTypes.toList()
} else {
listOf(intersectedUpperBounds)
}
} else {
@Suppress("UNCHECKED_CAST")
upperBounds as List<ConeKotlinType>
}
}
return newArguments
}
@@ -416,8 +416,21 @@ class ConstraintSystemCompleter(components: BodyResolveComponents, private val c
variableWithConstraints,
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
)
val resultTypeForOnlyInputTypes =
if (with(ConeConstraintSystemUtilContext) { variableWithConstraints.typeVariable.hasOnlyInputTypesAttribute() }) {
inferenceComponents.resultTypeResolver.findResultType(
c,
variableWithConstraints,
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN,
isForOnlyInputTypes = true
)
} else {
resultType
}
val variable = variableWithConstraints.typeVariable
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable))
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable), resultTypeForOnlyInputTypes)
}
companion object {
@@ -389,7 +389,7 @@ class FirCallCompleter(
}
return session.typeApproximator.approximateToSuperType(
this, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
this, TypeApproximatorConfiguration.IntermediateApproximationToSupertypeAfterCompletionInK2
) ?: this
}
@@ -495,7 +495,8 @@ class FirCallCompletionResultsWriterTransformer(
val initialType = candidate.substitutor.substituteOrSelf(type)
val substitutedType = finallySubstituteOrNull(initialType)
val finalType = typeApproximator.approximateToSuperType(
type = substitutedType ?: initialType, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference,
type = substitutedType ?: initialType,
TypeApproximatorConfiguration.IntermediateApproximationToSupertypeAfterCompletionInK2,
) ?: substitutedType
// This is probably a temporary hack, but it seems necessary because elvis has that attribute and it may leak further like
@@ -968,7 +969,7 @@ class FirCallCompletionResultsWriterTransformer(
arrayLiteral.transformChildren(this, expectedArrayElementType?.toExpectedType())
val arrayElementType =
session.typeContext.commonSuperTypeOrNull(arrayLiteral.arguments.map { it.resolvedType })?.let {
typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference)
typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.IntermediateApproximationToSupertypeAfterCompletionInK2)
?: it
} ?: expectedArrayElementType ?: session.builtinTypes.nullableAnyType.type
arrayLiteral.resultType =
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyResolveComponents) : FirTransformer<Any?>() {
companion object {
@@ -119,7 +120,9 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
}
val session = bodyResolveComponents.session
val subjectType = getSubjectType(session, whenExpression) ?: run {
val subjectType = getSubjectType(session, whenExpression)?.let {
session.typeApproximator.approximateToSuperType(it, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference) ?: it
} ?: run {
whenExpression.replaceExhaustivenessStatus(ExhaustivenessStatus.NotExhaustive.NO_ELSE_BRANCH)
return
}
@@ -1717,7 +1717,7 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT
)
} else {
session.typeApproximator.approximateToSuperType(
typeFromCallee.type, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
typeFromCallee.type, TypeApproximatorConfiguration.IntermediateApproximationToSupertypeAfterCompletionInK2
)
} ?: typeFromCallee.type
}
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
fun BodyResolveComponents.computeRepresentativeTypeForBareType(type: ConeClassLikeType, originalType: ConeKotlinType): ConeKotlinType? {
originalType.lowerBoundIfFlexible().fullyExpandedType(session).let {
@@ -30,6 +31,13 @@ fun BodyResolveComponents.computeRepresentativeTypeForBareType(type: ConeClassLi
return candidatesFromIntersectedTypes.firstOrNull()
}
session.typeApproximator.approximateToSuperType(
originalType,
TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
)?.let {
return computeRepresentativeTypeForBareType(type, it)
}
val originalClassLookupTag = (originalType as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag ?: return null
val castTypeAlias = type.lookupTag.toSymbol(session)?.fir as? FirTypeAlias
@@ -32,7 +32,12 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
// mutable operations
abstract fun addError(error: ConstraintSystemError)
abstract fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, position: FixVariableConstraintPosition<*>)
abstract fun fixVariable(
variable: TypeVariableMarker,
resultType: KotlinTypeMarker,
position: FixVariableConstraintPosition<*>,
resultTypeForOnlyInputTypes: KotlinTypeMarker = resultType
)
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
abstract fun resolveForkPointsConstraints()
@@ -58,8 +58,8 @@ class ResultTypeResolver(
return if (direction == ResolveDirection.TO_SUBTYPE) nothingType() else nullableAnyType()
}
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): KotlinTypeMarker {
findResultTypeOrNull(c, variableWithConstraints, direction)?.let { return it }
fun findResultType(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection, isForOnlyInputTypes: Boolean = false): KotlinTypeMarker {
findResultTypeOrNull(c, variableWithConstraints, direction, isForOnlyInputTypes)?.let { return it }
// no proper constraints
return c.getDefaultType(direction, variableWithConstraints.constraints, variableWithConstraints.typeVariable)
@@ -68,7 +68,8 @@ class ResultTypeResolver(
fun findResultTypeOrNull(
c: Context,
variableWithConstraints: VariableWithConstraints,
direction: ResolveDirection
direction: ResolveDirection,
isForOnlyInputTypes: Boolean = false,
): KotlinTypeMarker? {
val resultTypeFromEqualConstraint = findResultIfThereIsEqualsConstraint(c, variableWithConstraints)
if (resultTypeFromEqualConstraint != null) {
@@ -83,7 +84,7 @@ class ResultTypeResolver(
}
}
val subType = c.findSubType(variableWithConstraints)
val subType = c.findSubType(variableWithConstraints, isForOnlyInputTypes)
// Super type should be the most flexible, sub type should be the least one
val superType = c.findSuperType(variableWithConstraints).makeFlexibleIfNecessary(c, variableWithConstraints.constraints)
@@ -208,8 +209,8 @@ class ResultTypeResolver(
return constraints.singleOrNull { it.kind.isLower() }?.isNullabilityConstraint ?: false
}
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints)
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints, isForOnlyInputTypes: Boolean): KotlinTypeMarker? {
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints, isForOnlyInputTypes)
if (lowerConstraintTypes.isNotEmpty()) {
val types = sinkIntegerLiteralTypes(lowerConstraintTypes)
@@ -259,7 +260,7 @@ class ResultTypeResolver(
private fun Context.computeCommonSuperType(types: List<KotlinTypeMarker>): KotlinTypeMarker =
with(NewCommonSuperTypeCalculator) { commonSuperType(types) }
private fun Context.prepareLowerConstraints(constraints: List<Constraint>): List<KotlinTypeMarker> {
private fun Context.prepareLowerConstraints(constraints: List<Constraint>, isForOnlyInputTypes: Boolean): List<KotlinTypeMarker> {
var atLeastOneProper = false
var atLeastOneNonProper = false
@@ -268,7 +269,15 @@ class ResultTypeResolver(
for (constraint in constraints) {
if (constraint.kind != ConstraintKind.LOWER) continue
val type = constraint.type
var type = constraint.type
// The call to commonSuperTypes will replace arguments that have recursive supertypes with star projections,
// which will lead to a different resulting type than approximating it first.
// This breaks the @OnlyInputTypes check for captured types with recursive super types.
if (isForOnlyInputTypes && isK2 && hasRecursiveTypeParametersWithGivenSelfType(type.typeConstructor())) {
type = typeApproximator.approximateToSuperType(type, TypeApproximatorConfiguration.InternalTypesApproximation) ?: type
}
lowerConstraintTypes.add(type)
if (isProperTypeForFixation(type)) {
@@ -567,6 +567,7 @@ class NewConstraintSystemImpl(
variable: TypeVariableMarker,
resultType: KotlinTypeMarker,
position: FixVariableConstraintPosition<*>,
resultTypeForOnlyInputTypes: KotlinTypeMarker,
) = with(utilContext) {
checkState(State.BUILDING, State.COMPLETION)
@@ -593,7 +594,7 @@ class NewConstraintSystemImpl(
// Substitute freshly fixed type variable into missed constraints
substituteMissedConstraints()
postponeOnlyInputTypesCheck(variableWithConstraints, resultType)
postponeOnlyInputTypesCheck(variableWithConstraints, resultTypeForOnlyInputTypes)
doPostponedComputationsIfAllVariablesAreFixed()
}
@@ -113,6 +113,24 @@ open class TypeApproximatorConfiguration {
override val convertToNonRawVersionAfterApproximationInK2: Boolean get() = true
}
object IntermediateApproximationToSupertypeAfterCompletionInK2 :
AbstractCapturedTypesApproximation(null) {
override val integerLiteralConstantType: Boolean get() = true
override val integerConstantOperatorType: Boolean get() = true
override val intersectionTypesInContravariantPositions: Boolean get() = true
override val convertToNonRawVersionAfterApproximationInK2: Boolean get() = true
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean {
/**
* Only approximate captured types when they contain a raw supertype.
* This is an awful hack required to keep K1 compatibility.
* See [convertToNonRawVersionAfterApproximationInK2].
*/
return type.captureStatus(ctx) == CaptureStatus.FROM_EXPRESSION && with(ctx) { type.hasRawSuperType() }
}
}
object TypeArgumentApproximation : AbstractCapturedTypesApproximation(null) {
override val integerLiteralConstantType: Boolean get() = true
override val integerConstantOperatorType: Boolean get() = true
@@ -2,9 +2,6 @@
// ISSUE: KT-52838
// IGNORE_LIGHT_ANALYSIS
// IGNORE_BACKEND_K2: WASM
// REASON: That still doesn't work properly with PCLA, but accidentally don't fails for other tests but WASM
// (see KT-52838 for tracking and same-named diagnostic test)
fun box(): String {
build {
@@ -1,10 +1,6 @@
// ISSUE: KT-52838
// JVM_ABI_K1_K2_DIFF: KT-64738
// IGNORE_BACKEND_K2: WASM
// REASON: That still doesn't work properly with PCLA, but accidentally don't fails for other tests but WASM
// (see KT-52838 for tracking and same-named diagnostic test)
fun box(): String {
build {
this as DerivedBuildee<*>
@@ -1,3 +1,9 @@
MODULE main
Missing in K2
TestKt$example$2.class
CLASS TestKt$example$1.class
Property: class.signature
K1
Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function1<*Lkotlin/Unit;>;
K2
NULL
+33
View File
@@ -0,0 +1,33 @@
MODULE main
Missing in K1
_1Kt$sam$Consumer$0.class
CLASS User$use$1.class
Property: class.signature
K1
<T:Ljava/lang/Object;>Ljava/lang/Object;LConsumer;
K2
NULL
Property: class.superClassInternalName
K1
java/lang/Object
K2
kotlin/jvm/internal/Lambda
Property: class.superInterfaces
K1
[Consumer]
K2
[kotlin/jvm/functions/Function1]
K1
consume(Ljava/lang/Object;)V [public, final]
K2
---
K1
---
K2
invoke(Ljava/lang/Object;)V [public, final]
FIELD INSTANCE:LUser$use$1;
Property: field.signature
K1
LUser$use$1<TT;>;
K2
NULL
+1
View File
@@ -3,6 +3,7 @@
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// JVM_ABI_K1_K2_DIFF: KT-64954
// FILE: Promise.java
import org.jetbrains.annotations.NotNull;
@@ -0,0 +1,3 @@
MODULE main
Missing in K1
BoxKt$test$2.class
@@ -1,6 +1,7 @@
// TARGET_BACKEND: JVM
// FULL_JDK
// JVM_TARGET: 1.8
// JVM_ABI_K1_K2_DIFF: KT-64954
// FILE: J.java
import java.util.function.*;
@@ -1,8 +1,8 @@
// ISSUE: KT-62959
fun bar(x: Inv<out CharSequence>) {
x.foo { <!ARGUMENT_TYPE_MISMATCH("CapturedType(out kotlin.CharSequence); kotlin.CharSequence")!>it<!> }
x.bar { <!ARGUMENT_TYPE_MISMATCH("CapturedType(out kotlin.CharSequence); kotlin.CharSequence"), TYPE_MISMATCH("CapturedType(out kotlin.CharSequence); CapturedType(out kotlin.CharSequence)")!>it.e()<!> }
x.foo { it }
x.bar { it.e() }
}
interface Inv<E> {
@@ -5,10 +5,10 @@ class Bound<T: Number>(val value: T)
fun test_1() {
val b: Bound<in Int> = Bound(1)
val vl: Number = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>b.value<!>
val vl: Number = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(in kotlin.Int)")!>b.value<!>
}
fun test_2() {
val b: Bound<*> = Bound(1)
val vl: Number = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>b.value<!>
val vl: Number = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)")!>b.value<!>
}
@@ -0,0 +1,18 @@
interface Inv<T : CharSequence>
fun <E : CharSequence> id(i: Inv<E>): Inv<E> = i
fun foo1(x: Inv<in String>) {
val y = <!DEBUG_INFO_EXPRESSION_TYPE("Inv<CapturedType(in kotlin.String)>")!>id(x)<!> // Should return Inv<in String>
bar1(y)
}
fun bar1(i: Inv<in String>) {}
fun foo2(x: Inv<in Nothing>) {
// Inv<out kotlin.CharSequence> is OK here, because it's still a subtype of Inv<in Nothing>
val y = <!DEBUG_INFO_EXPRESSION_TYPE("Inv<CapturedType(in kotlin.Nothing)>")!>id(x)<!>
bar2(y)
}
fun bar2(i: Inv<in Nothing>) {}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
interface Inv<T : CharSequence>
fun <E : CharSequence> id(i: Inv<E>): Inv<E> = i
@@ -0,0 +1,13 @@
// ISSUE: KT-57958
fun ListVM<*>.foo() {
val currentItem1: MutableProperty<out Any?> = <!DEBUG_INFO_EXPRESSION_TYPE("MutableProperty<CapturedType(*)?>")!>currentItem<!>
}
interface MutableProperty<T> {
var value: T
}
interface ListVM<TItemVM> {
val currentItem: MutableProperty<TItemVM?>
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// ISSUE: KT-57958
fun ListVM<*>.foo() {
@@ -20,11 +20,11 @@ fun getTag7(): Tag7<*> = Tag7<Int> { }
fun getTag8(): Tag8<*> = Tag8<Int> { 1 }
fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag2().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag3().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag4().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Any?>")!>getTag5().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<CapturedType(*)>")!>getTag().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in CapturedType(*)>")!>getTag2().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<CapturedType(*)>")!>getTag3().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in CapturedType(*)>")!>getTag4().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action2<CapturedType(*)>")!>getTag5().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in kotlin.Any?>")!>getTag6().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<kotlin.Any?>")!>getTag7().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action2<kotlin.Any?>")!>getTag8().action<!>
@@ -0,0 +1,16 @@
// FIR_IDENTICAL
// FILE: Inlay.java
public interface Inlay<T extends EditorCustomElementRenderer> {
@org.jetbrains.annotations.NotNull T getRenderer();
}
// FILE: test.kt
interface EditorCustomElementRenderer
interface PresentationContainerRenderer<Constraints : Any> : EditorCustomElementRenderer
fun test(inlay: Inlay<out PresentationContainerRenderer<*>>) {
inlay.renderer.addOrUpdate()
}
fun <T : Any> PresentationContainerRenderer<T>.addOrUpdate() {}
@@ -44,7 +44,7 @@ public class Bar<T> {
fun takeStarBar(x: Bar<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main2() {
@@ -58,7 +58,7 @@ fun main2() {
fun takeStarFoo2(x: Foo2<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main3() {
@@ -75,7 +75,7 @@ public class Bar2<T> {
fun takeStarBar2(x: Bar2<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main4() {
@@ -89,7 +89,7 @@ fun main4() {
fun takeStarFoo3(x: Foo3<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main5() {
@@ -107,7 +107,7 @@ class Bar3<T> {
fun takeStarBar3(x: Bar3<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main6() {
@@ -44,7 +44,7 @@ public class Bar<T> {
fun takeStarBar(x: Bar<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main2() {
@@ -58,7 +58,7 @@ fun main2() {
fun takeStarFoo2(x: Foo2<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main3() {
@@ -75,7 +75,7 @@ public class Bar2<T> {
fun takeStarBar2(x: Bar2<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main4() {
@@ -89,7 +89,7 @@ fun main4() {
fun takeStarFoo3(x: Foo3<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main5() {
@@ -107,7 +107,7 @@ class Bar3<T> {
fun takeStarBar3(x: Bar3<*>) {
x.value = <!ASSIGNMENT_TYPE_MISMATCH!>"test"<!>
x.value <!UNRESOLVED_REFERENCE!>+=<!> "test"
x.value <!NONE_APPLICABLE!>+=<!> "test"
}
fun main6() {
@@ -0,0 +1,13 @@
// !CHECK_TYPE
class A<T> {
fun foo(): T = null!!
}
fun <E> A<E>.bar(): A<in E> = this
fun baz(x: A<out CharSequence>) {
x.bar() checkType { _<A<*>>() }
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(in CapturedType(out kotlin.CharSequence))")!>x.bar().foo()<!> checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() } // See KT-10448
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(in CapturedType(out kotlin.CharSequence))")!>x.bar().foo()<!> checkType { _<CharSequence>() } // Inference change in K2
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !CHECK_TYPE
class A<T> {
@@ -9,5 +8,6 @@ fun <E> A<E>.bar(): A<in E> = this
fun baz(x: A<out CharSequence>) {
x.bar() checkType { _<A<*>>() }
x.bar().foo() checkType { _<Any?>() } // See KT-10448
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x.bar().foo()<!> checkType { _<Any?>() } // See KT-10448
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x.bar().foo()<!> checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><CharSequence>() } // Inference change in K2
}
@@ -19,17 +19,17 @@ public class JavaWriterAppender {
// FILE: main.kt
fun test() {
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<*>")!>WriterAppender.newBuilder()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<out WriterAppender.Builder1<*>>")!>WriterAppender.Builder1()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)")!>WriterAppender.newBuilder()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<CapturedType(*)>")!>WriterAppender.Builder1()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("WriterAppender.Builder1<*> & WriterAppender.Builder2<*>")!>WriterAppender.intersectTwoSelfTypes()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)")!>WriterAppender.intersectTwoSelfTypes()<!>
}
fun testJava(appender: JavaWriterAppender) {
<!DEBUG_INFO_EXPRESSION_TYPE("JavaWriterAppender.Builder1<*>..JavaWriterAppender.Builder1<*>?!")!>appender.newBuilder()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("JavaWriterAppender.Builder1<out JavaWriterAppender.Builder1<*>..JavaWriterAppender.Builder1<*>?!>")!>appender.Builder1()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)!!..CapturedType(*)?!")!>appender.newBuilder()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("JavaWriterAppender.Builder1<CapturedType(*)>")!>appender.Builder1()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("JavaWriterAppender.Builder1<*> & JavaWriterAppender.Builder2<*>..JavaWriterAppender.Builder1<*>? & JavaWriterAppender.Builder2<*>?")!>appender.intersectTwoSelfTypes()<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)!!..CapturedType(*)?!")!>appender.intersectTwoSelfTypes()<!>
}
object WriterAppender {
@@ -65,17 +65,17 @@ fun test10(b: Boolean) {
}
fun test11(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>foo11 { 1 }.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out kotlin.Any)")!>foo11 { 1 }.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>foo11 { 2 }.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out kotlin.Any)")!>foo11 { 2 }.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
fun test12(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>foo12 { 1 }.value.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out kotlin.Any)")!>foo12 { 1 }.value.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>foo12 { 2 }.value.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out kotlin.Any)")!>foo12 { 2 }.value.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
@@ -91,17 +91,17 @@ fun test20(b: Boolean) {
}
fun test21(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo21 { 1 }.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo21 { 1 }.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo21 { 2 }.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo21 { 2 }.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
fun test22(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo22 { 1 }.value.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo22 { 1 }.value.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo22 { 2 }.value.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo22 { 2 }.value.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
@@ -117,17 +117,17 @@ fun test30(b: Boolean) {
}
fun test31(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo31 { 1 }.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo31 { 1 }.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo31 { 2 }.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo31 { 2 }.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
fun test32(b: Boolean) {
var x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo32 { 1 }.value.value<!>
var x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo32 { 1 }.value.value<!>
if (b) {
x = <!DEBUG_INFO_EXPRESSION_TYPE("I1")!>foo32 { 2 }.value.value<!>
x = <!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out I1)")!>foo32 { 2 }.value.value<!>
}
x.<!UNRESOLVED_REFERENCE!>bar<!>()
}
@@ -0,0 +1,18 @@
// FIR_IDENTICAL
abstract class FirBasedSymbol<E : FirDeclaration> {
val fir: E get() = null!!
}
abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>()
sealed class FirDeclaration
sealed class FirCallableDeclaration : FirDeclaration()
class FirFunction : FirCallableDeclaration()
class FirVariable : FirCallableDeclaration()
val FirCallableSymbol<*>.isExtension: Boolean
get() = when (fir) {
is FirFunction -> true
is FirVariable -> false
}
@@ -10,6 +10,6 @@ fun <T> listOf(): List<T> = null!!
// Unresolved reference is ok here:
// we can't create a substituted signature for type alias constructor
// since it has 'out' type projection in 'in' position.
val test1 = BOutIn(<!ARGUMENT_TYPE_MISMATCH!>listOf()<!>, null!!)
val test1 = <!UPPER_BOUND_VIOLATED!>BOutIn(<!ARGUMENT_TYPE_MISMATCH!>listOf()<!>, null!!)<!>
val test2 = BInIn(listOf(), null!!)
val test2 = <!UPPER_BOUND_VIOLATED!>BInIn(listOf(), null!!)<!>
@@ -7,7 +7,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
CALL 'public open fun someFunction (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=example.Hello<out @[FlexibleNullability] kotlin.String?> origin=SAM_CONVERSION typeOperand=example.Hello<out @[FlexibleNullability] kotlin.String?>
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.Nothing?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -17,7 +17,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
CALL 'public open fun plus (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): @[FlexibleNullability] example.SomeJavaClass<@[FlexibleNullability] A of example.SomeJavaClass?>? declared in example.SomeJavaClass' type=@[FlexibleNullability] example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?>? origin=PLUS
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=example.Hello<out @[FlexibleNullability] kotlin.String?> origin=SAM_CONVERSION typeOperand=example.Hello<out @[FlexibleNullability] kotlin.String?>
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.Nothing?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -26,7 +26,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
CALL 'public open fun get (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=example.Hello<out @[FlexibleNullability] kotlin.String?> origin=SAM_CONVERSION typeOperand=example.Hello<out @[FlexibleNullability] kotlin.String?>
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.Nothing?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -36,17 +36,18 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
CALL 'public open fun plus (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): @[FlexibleNullability] example.SomeJavaClass<@[FlexibleNullability] A of example.SomeJavaClass?>? declared in example.SomeJavaClass' type=@[FlexibleNullability] example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?>? origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=example.Hello<out @[FlexibleNullability] kotlin.String?> origin=SAM_CONVERSION typeOperand=example.Hello<out @[FlexibleNullability] kotlin.String?>
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.Nothing?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <anonymous> (it: @[FlexibleNullability] kotlin.String?): kotlin.Unit declared in <root>.test'
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CALL 'public open fun set (i: kotlin.Int, hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
$this: TYPE_OP type=example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?> origin=IMPLICIT_CAST typeOperand=example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?>
GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
i: CONST Int type=kotlin.Int value=0
hello: TYPE_OP type=example.Hello<out @[FlexibleNullability] kotlin.String?> origin=SAM_CONVERSION typeOperand=example.Hello<out @[FlexibleNullability] kotlin.String?>
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.Nothing?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
BLOCK_BODY
@@ -16,7 +16,7 @@ fun test() {
return Unit
}
/*-> Hello<out @FlexibleNullability String?> */)
a.set(i = 0, hello = local fun <anonymous>(it: @FlexibleNullability String?) {
a /*as SomeJavaClass<out @FlexibleNullability String?> */.set(i = 0, hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> Hello<out @FlexibleNullability String?> */)
@@ -76,7 +76,7 @@ FILE fqName:<root> fileName:/genericFunWithStar.kt
VALUE_PARAMETER name:serializers index:0 type:kotlin.Array<out <root>.I<*>> varargElementType:<root>.I<*> [vararg]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun bar (vararg serializers: <root>.I<*>): <root>.I<*> declared in <root>.Box'
CALL 'public abstract fun foo <F> (tSerializer: <root>.I<F of <root>.Box.foo>): <root>.I<<root>.Box<F of <root>.Box.foo>> declared in <root>.Box' type=<root>.I<out <root>.Box<*>> origin=null
CALL 'public abstract fun foo <F> (tSerializer: <root>.I<F of <root>.Box.foo>): <root>.I<<root>.Box<F of <root>.Box.foo>> declared in <root>.Box' type=<root>.I<out <root>.Box<out <root>.IBase>> origin=null
<F>: <root>.IBase
$this: GET_VAR '<this>: <root>.Box<T of <root>.Box> declared in <root>.Box.bar' type=<root>.Box<T of <root>.Box> origin=null
tSerializer: CALL 'public final fun get (index: kotlin.Int): T of kotlin.Array declared in kotlin.Array' type=<root>.I<*> origin=null
@@ -17917,6 +17917,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingFromArgumentOfFlexibleType.kt");
}
@Test
@TestMetadata("capturingOfDnn.kt")
public void testCapturingOfDnn() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturingOfDnn.kt");
}
@Test
@TestMetadata("differentCapturedTypes.kt")
public void testDifferentCapturedTypes() throws Exception {
@@ -33742,6 +33748,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
}
@Test
@TestMetadata("ExhaustiveOnCaptured.kt")
public void testExhaustiveOnCaptured() throws Exception {
runTest("compiler/testData/diagnostics/tests/sealed/ExhaustiveOnCaptured.kt");
}
@Test
@TestMetadata("ExhaustiveOnRoot.kt")
public void testExhaustiveOnRoot() throws Exception {
@@ -27,7 +27,7 @@ fun Any.case_2() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & ClassWithSixTypeParameters<*, *, *, *, *, *>")!>this<!>.test()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & ClassWithSixTypeParameters<*, *, *, *, *, *>")!>this<!>.x
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & ClassWithSixTypeParameters<*, *, *, *, *, *>")!>this<!>.y
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>y<!>
}
}
@@ -49,7 +49,7 @@ fun <T> T?.case_4() {
<!DEBUG_INFO_EXPRESSION_TYPE("T? & ClassWithSixTypeParameters<*, *, *, *, *, *> & T?!!")!>this<!>.test()
<!DEBUG_INFO_EXPRESSION_TYPE("T? & ClassWithSixTypeParameters<*, *, *, *, *, *> & T?!!")!>this<!>.x
<!DEBUG_INFO_EXPRESSION_TYPE("T? & ClassWithSixTypeParameters<*, *, *, *, *, *> & T?!!")!>this<!>.y
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(*)")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>y<!>
}
}
@@ -62,7 +62,7 @@ fun <T> ClassWithSixTypeParameters<out T, *, T, in T?, *, T>.case_5() {
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithSixTypeParameters<out T, *, T, in T?, *, T> & InterfaceWithFiveTypeParameters1<*, *, *, *, *> & ClassWithSixTypeParameters<out T, *, T, in T?, *, T>")!>this<!>.test()
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithSixTypeParameters<out T, *, T, in T?, *, T> & InterfaceWithFiveTypeParameters1<*, *, *, *, *> & ClassWithSixTypeParameters<out T, *, T, in T?, *, T>")!>this<!>.x
<!DEBUG_INFO_EXPRESSION_TYPE("ClassWithSixTypeParameters<out T, *, T, in T?, *, T> & InterfaceWithFiveTypeParameters1<*, *, *, *, *> & ClassWithSixTypeParameters<out T, *, T, in T?, *, T>")!>this<!>.y
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out T)")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T")!>y<!>
}
}
@@ -86,8 +86,8 @@ fun <T> Inv<out T>.case_7() {
if (this.prop_3 is MutableList<*>) {
this.prop_3
this.prop_3[0]
<!DEBUG_INFO_EXPRESSION_TYPE("T & kotlin.collections.MutableList<*> & T!!")!>prop_3<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & kotlin.collections.MutableList<*> & T!!")!>prop_3<!>[0]
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out T) & kotlin.collections.MutableList<*> & CapturedType(out T)!!")!>prop_3<!>
<!DEBUG_INFO_EXPRESSION_TYPE("CapturedType(out T) & kotlin.collections.MutableList<*> & CapturedType(out T)!!")!>prop_3<!>[0]
}
}
@@ -229,6 +229,11 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun CapturedTypeMarker.typeParameter(): TypeParameterMarker?
fun CapturedTypeMarker.withNotNullProjection(): KotlinTypeMarker
/**
* Only for K2.
*/
fun CapturedTypeMarker.hasRawSuperType(): Boolean
fun TypeVariableMarker.defaultType(): SimpleTypeMarker
fun createTypeWithAlternativeForIntersectionResult(
@@ -533,6 +533,10 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
override fun CapturedTypeMarker.isOldCapturedType(): Boolean = this is CapturedType
override fun CapturedTypeMarker.hasRawSuperType(): Boolean {
error("Is not expected to be called in K1")
}
override fun KotlinTypeMarker.isNullableType(): Boolean {
require(this is KotlinType, this::errorMessage)
return TypeUtils.isNullableType(this)