diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java index 63ae5a9a417..c4e4ca48d69 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java @@ -1921,6 +1921,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt37627.kt"); } + @TestMetadata("kt38143.kt") + public void testKt38143() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index 18903fe4fa0..b8689a1b7a2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -79,13 +79,14 @@ class ConstraintInjector( possibleNewConstraints!!.add(typeVar to constraint) } typeCheckerContext.runIsSubtypeOf(lowerType, upperType) + var constraintsFromIsSubtype = true while (possibleNewConstraints != null) { val constraintsToProcess = possibleNewConstraints possibleNewConstraints = null for ((typeVariable, constraint) in constraintsToProcess!!) { - if (c.shouldWeSkipConstraint(typeVariable, constraint)) continue + if (c.shouldWeSkipConstraint(typeVariable, constraint, constraintsFromIsSubtype)) continue val constraints = c.notFixedTypeVariables[typeVariable.freshTypeConstructor(c)] ?: typeCheckerContext.fixedTypeVariable(typeVariable) @@ -108,6 +109,7 @@ class ConstraintInjector( ) { break } + constraintsFromIsSubtype = false } } @@ -115,11 +117,17 @@ class ConstraintInjector( c.maxTypeDepthFromInitialConstraints = max(c.maxTypeDepthFromInitialConstraints, initialType.typeDepth()) } - private fun Context.shouldWeSkipConstraint(typeVariable: TypeVariableMarker, constraint: Constraint): Boolean { + private fun Context.shouldWeSkipConstraint( + typeVariable: TypeVariableMarker, + constraint: Constraint, + constraintsFromIsSubtype: Boolean + ): Boolean { assert(constraint.kind != ConstraintKind.EQUALITY) val constraintType = constraint.type - if (!isAllowedType(constraintType)) return true + // TODO: seems these coditions never met, at least in the tests, we need either to find a test for it or drop the check + if (!constraintsFromIsSubtype && !isAllowedType(constraintType)) + return true if (constraintType.typeConstructor() == typeVariable.freshTypeConstructor()) { if (constraintType.lowerBoundIfFlexible().isMarkedNullable() && constraint.kind == LOWER) return false // T? <: T diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt new file mode 100644 index 00000000000..81594d30c95 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt @@ -0,0 +1,37 @@ +// FIR_IDENTICAL +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +// Generic interface, nothing interesting here +interface UseCase { + fun execute(input: I): O +} + +// We don't want to call use cases without input with explicit Unit argument, so we create this handy extension +fun UseCase.execute(): O = execute(Unit) + +class Foo : UseCase>>> { + override fun execute(input: Unit) = listOf(listOf(listOf("foo"))) +} + +class Bar : UseCase>> { + override fun execute(input: Unit) = listOf(listOf("bar")) +} + +class Baz : UseCase>>>>>> { + override fun execute(input: Unit) = listOf(listOf(listOf(listOf(listOf(listOf("foo")))))) +} + +fun main() { + val foo = Foo() + foo.execute(Unit) // Member: OK both versions + foo.execute() // Extension: OI - OK, NI - was error: "Not enough information to infer type variable O" + + val bar = Bar() + bar.execute(Unit) // Member: OK both versions + bar.execute() // Extension: OK both versions + + val baz = Baz() + baz.execute(Unit) + baz.execute() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.txt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.txt new file mode 100644 index 00000000000..5d407aac21a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.txt @@ -0,0 +1,35 @@ +package + +public fun main(): kotlin.Unit +public fun UseCase.execute(): O + +public final class Bar : UseCase>> { + public constructor Bar() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun execute(/*0*/ input: kotlin.Unit): kotlin.collections.List> + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Baz : UseCase>>>>>> { + public constructor Baz() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun execute(/*0*/ input: kotlin.Unit): kotlin.collections.List>>>>> + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Foo : UseCase>>> { + public constructor Foo() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun execute(/*0*/ input: kotlin.Unit): kotlin.collections.List>> + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface UseCase { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun execute(/*0*/ input: I): O + 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/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 71e14fe7e30..11de66aa3f4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -2931,6 +2931,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt37627.kt"); } + @TestMetadata("kt38143.kt") + public void testKt38143() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 9543f138b7d..5742ead30a2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -2931,6 +2931,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt37627.kt"); } + @TestMetadata("kt38143.kt") + public void testKt38143() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt38143.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt");