diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt index 4f17a2eab6a..1db23b54f78 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeTypes.kt @@ -141,7 +141,7 @@ fun ConeKotlinType.lowerBoundIfFlexible() = (this as? ConeFlexibleType)?.lowerBo class ConeCapturedTypeConstructor( val projection: ConeKotlinTypeProjection, var supertypes: List? = null -) : TypeConstructorMarker +) : CapturedTypeConstructorMarker class ConeCapturedType( val captureStatus: CaptureStatus, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 086afca8621..d5073affafd 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -143,6 +143,21 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty return typeConstructor } + override fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker { + require(this is ConeCapturedType) + return this.constructor + } + + override fun CapturedTypeMarker.captureStatus(): CaptureStatus { + require(this is ConeCapturedType) + return this.captureStatus + } + + override fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker { + require(this is ConeCapturedTypeConstructor) + return this.projection + } + override fun KotlinTypeMarker.argumentsCount(): Int { require(this is ConeKotlinType) diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index db127d74d92..0c22a179296 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -10246,6 +10246,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nestedLambdas.kt"); } + @TestMetadata("nonFixedVariableFromBothBranches.kt") + public void testNonFixedVariableFromBothBranches() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt"); + } + @TestMetadata("nonFixedVariableInsideFlexibleType.kt") public void testNonFixedVariableInsideFlexibleType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableInsideFlexibleType.kt"); diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index 0e8db664b79..1417d490b65 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -72,6 +72,15 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon override fun SimpleTypeMarker.typeConstructor() = (this as IrSimpleType).classifier + override fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker = + error("Captured types should be used for IrTypes") + + override fun CapturedTypeMarker.captureStatus(): CaptureStatus = + error("Captured types should be used for IrTypes") + + override fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker = + error("Captured types should be used for IrTypes") + override fun KotlinTypeMarker.argumentsCount(): Int = when (this) { is IrSimpleType -> arguments.size diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt index 2ed6549be83..a2ccaad048a 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -257,17 +257,22 @@ object NewCommonSuperTypeCalculator { val parameter = constructor.getParameter(index) var thereIsStar = false val typeProjections = correspondingSuperTypes.mapNotNull { - it.getArgumentOrNull(index)?.let { typeArgument -> - when { - typeArgument.isStarProjection() -> { - thereIsStar = true - null - } + val typeArgumentFromSupertype = it.getArgumentOrNull(index) ?: return@mapNotNull null - typeArgument.getType().lowerBoundIfFlexible().isStubType() -> null + // We have to uncapture types with status FOR_SUBTYPING because such captured types are creating during + // `findCorrespondingSupertypes` call. Normally, we shouldn't create intermediate captured types here, it's needed only + // to check subtyping. It'll be fixed but for a while we do this uncapturing here + val typeArgument = uncaptureFromSubtyping(typeArgumentFromSupertype) - else -> typeArgument + when { + typeArgument.isStarProjection() -> { + thereIsStar = true + null } + + typeArgument.getType().lowerBoundIfFlexible().isStubType() -> null + + else -> typeArgument } } @@ -295,6 +300,13 @@ object NewCommonSuperTypeCalculator { return createSimpleType(constructor, arguments, nullable = false) } + private fun TypeSystemCommonSuperTypesContext.uncaptureFromSubtyping(typeArgument: TypeArgumentMarker): TypeArgumentMarker { + val capturedType = typeArgument.getType().asSimpleType()?.asCapturedType() ?: return typeArgument + if (capturedType.captureStatus() != CaptureStatus.FOR_SUBTYPING) return typeArgument + + return capturedType.typeConstructor().projection() + } + // no star projections in arguments private fun TypeSystemCommonSuperTypesContext.calculateArgument( parameter: TypeParameterMarker, diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt new file mode 100644 index 00000000000..3b672bd96c7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +// FILE: JavaTest.java + +public class JavaTest { + public static Number[] createNumberArray() { return null; } +} + +// FILE: test.kt + +fun select(x: K, y: K): K = x + +fun foo(f: () -> R): R = f() + +fun test(n: Number) { + val a = select(foo { JavaTest.createNumberArray() }, emptyArray()) + + ..kotlin.Array?)")!>a +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.txt b/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.txt new file mode 100644 index 00000000000..f301afe0b13 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.txt @@ -0,0 +1,15 @@ +package + +public fun foo(/*0*/ f: () -> R): R +public fun select(/*0*/ x: K, /*1*/ y: K): K +public fun test(/*0*/ n: kotlin.Number): kotlin.Unit + +public open class JavaTest { + public constructor JavaTest() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public open fun createNumberArray(): kotlin.Array<(out) kotlin.Number!>! +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 85bc38eb509..df21d70027a 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10253,6 +10253,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nestedLambdas.kt"); } + @TestMetadata("nonFixedVariableFromBothBranches.kt") + public void testNonFixedVariableFromBothBranches() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt"); + } + @TestMetadata("nonFixedVariableInsideFlexibleType.kt") public void testNonFixedVariableInsideFlexibleType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableInsideFlexibleType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 158f84bae5d..cf203898524 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10248,6 +10248,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nestedLambdas.kt"); } + @TestMetadata("nonFixedVariableFromBothBranches.kt") + public void testNonFixedVariableFromBothBranches() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableFromBothBranches.kt"); + } + @TestMetadata("nonFixedVariableInsideFlexibleType.kt") public void testNonFixedVariableInsideFlexibleType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/nonFixedVariableInsideFlexibleType.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt index 404a58d0b38..efe2dcf1829 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt @@ -26,11 +26,12 @@ import org.jetbrains.kotlin.types.Variance.IN_VARIANCE import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor +import org.jetbrains.kotlin.types.model.CapturedTypeConstructorMarker import org.jetbrains.kotlin.types.model.CapturedTypeMarker import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.builtIns -interface CapturedTypeConstructor : TypeConstructor { +interface CapturedTypeConstructor : CapturedTypeConstructorMarker, TypeConstructor { val projection: TypeProjection } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 1499fd4b743..65ac8473f56 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.inference.CapturedType +import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructorImpl import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.hasExactAnnotation @@ -138,6 +139,16 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy return this.constructor } + override fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker { + require(this is NewCapturedType, this::errorMessage) + return this.constructor + } + + override fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker { + require(this is NewCapturedTypeConstructor, this::errorMessage) + return this.projection + } + override fun KotlinTypeMarker.argumentsCount(): Int { require(this is KotlinType, this::errorMessage) return this.arguments.size diff --git a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index 7f821af9b6c..496e7afd70f 100644 --- a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -26,6 +26,8 @@ interface TypeArgumentListMarker interface TypeVariableMarker interface TypeVariableTypeConstructorMarker : TypeConstructorMarker +interface CapturedTypeConstructorMarker : TypeConstructorMarker + interface TypeSubstitutorMarker @@ -147,7 +149,6 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui fun KotlinTypeMarker.mayBeTypeVariable(): Boolean fun CapturedTypeMarker.typeConstructorProjection(): TypeArgumentMarker - fun CapturedTypeMarker.captureStatus(): CaptureStatus fun DefinitelyNotNullTypeMarker.original(): SimpleTypeMarker @@ -187,6 +188,10 @@ interface TypeSystemContext : TypeSystemOptimizationContext { fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker + fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker + fun CapturedTypeMarker.captureStatus(): CaptureStatus + fun CapturedTypeConstructorMarker.projection(): TypeArgumentMarker + fun KotlinTypeMarker.argumentsCount(): Int fun KotlinTypeMarker.getArgument(index: Int): TypeArgumentMarker