diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 056ad73d115..3788486941a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -143,7 +143,7 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT } @Test - @TestMetadata("javaAnnotationArrayValueDefault.kt") + @TestMetadata("javaAnnotatestInferenceWithTypeVariableInsideCapturedType tionArrayValueDefault.kt") public void testJavaAnnotationArrayValueDefault() throws Exception { runTest("compiler/testData/codegen/box/annotations/javaAnnotationArrayValueDefault.kt"); } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt index 06045c7b653..92ead9ac340 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt @@ -94,7 +94,7 @@ class ConstraintIncorporator( val freshTypeConstructor = typeVariable.freshTypeConstructor() for (typeVariableWithConstraint in this@insideOtherConstraint.allTypeVariablesWithConstraints) { val constraintsWhichConstraintMyVariable = typeVariableWithConstraint.constraints.filter { - it.type.contains { it.typeConstructor() == freshTypeConstructor } + containsTypeVariable(it.type, freshTypeConstructor) } constraintsWhichConstraintMyVariable.forEach { generateNewConstraint(typeVariableWithConstraint.typeVariable, it, typeVariable, constraint) @@ -130,7 +130,7 @@ class ConstraintIncorporator( otherConstraint: Constraint ) { val isBaseGenericType = baseConstraint.type.argumentsCount() != 0 - val isOtherCapturedType = otherConstraint.type.isCapturedType() + val isBaseOrOtherCapturedType = baseConstraint.type.isCapturedType() || otherConstraint.type.isCapturedType() val (type, needApproximation) = when (otherConstraint.kind) { ConstraintKind.EQUALITY -> { otherConstraint.type to false @@ -145,9 +145,9 @@ class ConstraintIncorporator( * incorporatedConstraint = Approx(CapturedType(out Number)) <: TypeVariable(A) => Nothing <: TypeVariable(A) * TODO: implement this for generics and captured types */ - if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) { + if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isBaseOrOtherCapturedType) { nothingType() to false - } else if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) { + } else if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isBaseOrOtherCapturedType) { otherConstraint.type to false } else { createCapturedType( @@ -168,9 +168,9 @@ class ConstraintIncorporator( * incorporatedConstraint = TypeVariable(A) <: Approx(CapturedType(in Number)) => TypeVariable(A) <: Any? * TODO: implement this for generics and captured types */ - if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isOtherCapturedType) { + if (baseConstraint.kind == ConstraintKind.UPPER && !isBaseGenericType && !isBaseOrOtherCapturedType) { nullableAnyType() to false - } else if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isOtherCapturedType) { + } else if (baseConstraint.kind == ConstraintKind.LOWER && !isBaseGenericType && !isBaseOrOtherCapturedType) { otherConstraint.type to false } else { createCapturedType( diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt index 3583da575f2..a81b764a5a1 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt @@ -168,17 +168,33 @@ class VariableFixationFinder( } } -inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation( - type: KotlinTypeMarker, - isProper: (KotlinTypeMarker) -> Boolean -): Boolean { - if (!isProper(type)) return false - if (type.isCapturedType()) { - val projection = (type as? SimpleTypeMarker)?.asCapturedType()?.typeConstructorProjection() ?: return true - if (projection.isStarProjection()) return true +inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation(type: KotlinTypeMarker, isProper: (KotlinTypeMarker) -> Boolean) = + isProper(type) && extractProjectionsForAllCapturedTypes(type).all(isProper) - if (!isProper(projection.getType())) return false +@OptIn(ExperimentalStdlibApi::class) +fun TypeSystemInferenceExtensionContext.extractProjectionsForAllCapturedTypes(baseType: KotlinTypeMarker): Set { + val simpleBaseType = baseType.asSimpleType() + + return buildSet { + val projectionType = if (simpleBaseType is CapturedTypeMarker) { + val typeArgument = simpleBaseType.typeConstructorProjection().takeIf { !it.isStarProjection() } ?: return@buildSet + typeArgument.getType().also(::add) + } else baseType + val argumentsCount = projectionType.argumentsCount().takeIf { it != 0 } ?: return@buildSet + + for (i in 0 until argumentsCount) { + val typeArgument = projectionType.getArgument(i).takeIf { !it.isStarProjection() } ?: continue + addAll(extractProjectionsForAllCapturedTypes(typeArgument.getType())) + } + } +} + +fun TypeSystemInferenceExtensionContext.containsTypeVariable(type: KotlinTypeMarker, typeVariable: TypeConstructorMarker): Boolean { + if (type.contains { it.typeConstructor() == typeVariable }) return true + + val typeProjections = extractProjectionsForAllCapturedTypes(type) + + return typeProjections.any { typeProjectionsType -> + typeProjectionsType.contains { it.typeConstructor() == typeVariable } } - - return true } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index a8b6598eeaa..ba05158e1ff 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -336,9 +336,7 @@ class NewConstraintSystemImpl( val variableWithConstraints = notFixedTypeVariables.remove(freshTypeConstructor) for (otherVariableWithConstraints in notFixedTypeVariables.values) { - otherVariableWithConstraints.removeConstrains { otherConstraint -> - otherConstraint.type.contains { it.typeConstructor() == freshTypeConstructor } - } + otherVariableWithConstraints.removeConstrains { containsTypeVariable(it.type, freshTypeConstructor) } } storage.fixedTypeVariables[freshTypeConstructor] = resultType