diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 4bc40261f4c..55dc1bd897f 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -14243,6 +14243,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt50989.kt"); } + @Test + @TestMetadata("kt51148.kt") + public void testKt51148() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index fbcfb219f8e..95440e69295 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -14243,6 +14243,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt50989.kt"); } + @Test + @TestMetadata("kt51148.kt") + public void testKt51148() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index dc6b86a684a..373a5aefeae 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -14243,6 +14243,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt50989.kt"); } + @Test + @TestMetadata("kt51148.kt") + public void testKt51148() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception { 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 051d174d81a..ee8faf02f7e 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 @@ -67,7 +67,7 @@ class VariableFixationFinder( ): TypeVariableFixationReadiness = when { !notFixedTypeVariables.contains(variable) || dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN - isTypeInferenceForSelfTypesSupported && hasOnlyDeclaredUpperBoundSelfTypes(variable) -> + isTypeInferenceForSelfTypesSupported && areAllProperConstraintsSelfTypeBased(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_DECLARED_UPPER_BOUND_WITH_SELF_TYPES !variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY @@ -175,13 +175,29 @@ class VariableFixationFinder( } } - private fun Context.hasOnlyDeclaredUpperBoundSelfTypes(variable: TypeConstructorMarker): Boolean { - val constraints = notFixedTypeVariables[variable]?.constraints ?: return false - return constraints.isNotEmpty() && constraints.all { - val typeConstructor = it.type.typeConstructor() - it.position.from is DeclaredUpperBoundConstraintPosition<*> - && (hasRecursiveTypeParametersWithGivenSelfType(typeConstructor) || isRecursiveTypeParameter(typeConstructor)) + private fun Context.isSelfTypeConstraint(constraint: Constraint): Boolean { + val typeConstructor = constraint.type.typeConstructor() + return constraint.position.from is DeclaredUpperBoundConstraintPosition<*> + && (hasRecursiveTypeParametersWithGivenSelfType(typeConstructor) || isRecursiveTypeParameter(typeConstructor)) + } + + private fun Context.areAllProperConstraintsSelfTypeBased(variable: TypeConstructorMarker): Boolean { + val constraints = notFixedTypeVariables[variable]?.constraints?.takeIf { it.isNotEmpty() } ?: return false + + var hasSelfTypeConstraint = false + var hasOtherProperConstraint = false + + for (constraint in constraints) { + if (isSelfTypeConstraint(constraint)) { + hasSelfTypeConstraint = true + } + if (isProperArgumentConstraint(constraint)) { + hasOtherProperConstraint = true + } + if (hasSelfTypeConstraint && hasOtherProperConstraint) break } + + return hasSelfTypeConstraint && !hasOtherProperConstraint } } diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.fir.kt new file mode 100644 index 00000000000..8b4a41722c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.fir.kt @@ -0,0 +1,19 @@ +fun box(): String { + return someFunction<SomeEnum>() +} + +interface SomeInterface { + + val value: V + +} + +enum class SomeEnum { + + A, B, C + +} + +fun someFunction(): String where T : Enum, T : SomeInterface { + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt new file mode 100644 index 00000000000..78be7b6a591 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt @@ -0,0 +1,19 @@ +fun box(): String { + return someFunction() +} + +interface SomeInterface { + + val value: V + +} + +enum class SomeEnum { + + A, B, C + +} + +fun someFunction(): String where T : Enum, T : SomeInterface { + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.txt b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.txt new file mode 100644 index 00000000000..bfb4970fbd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/kt51148.txt @@ -0,0 +1,34 @@ +package + +public fun box(): kotlin.String +public fun > someFunction(): kotlin.String where T : SomeInterface + +public final enum class SomeEnum : kotlin.Enum { + enum entry A + + enum entry B + + enum entry C + + private constructor SomeEnum() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: SomeEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): SomeEnum + public final /*synthesized*/ fun values(): kotlin.Array +} + +public interface SomeInterface { + public abstract val value: V + 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 +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 03cbfd01f41..1de38fb3d86 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -14249,6 +14249,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt50989.kt"); } + @Test + @TestMetadata("kt51148.kt") + public void testKt51148() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/kt51148.kt"); + } + @Test @TestMetadata("labaledCall.kt") public void testLabaledCall() throws Exception {