diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index c89c8e29684..01d940d6ba7 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10664,6 +10664,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 53e217c4ca3..0ccf8061812 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem -import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible +import org.jetbrains.kotlin.resolve.calls.inference.addEqualityConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle @@ -285,7 +285,7 @@ class KotlinCallCompleter( } expectedType === TypeUtils.UNIT_EXPECTED_TYPE -> - csBuilder.addSubtypeConstraintIfCompatible( + csBuilder.addEqualityConstraintIfCompatible( returnType, csBuilder.builtIns.unitType, ExpectedTypeConstraintPosition(resolvedCall.atom) ) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index 5b627811850..bf3c6e3aa45 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -35,7 +35,6 @@ class PostponedArgumentsAnalyzer( fun canBeProper(type: KotlinTypeMarker): Boolean fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean - fun hasEqualNothingConstraint(type: KotlinTypeMarker): Boolean // mutable operations fun addOtherSystem(otherSystem: ConstraintStorage) @@ -123,7 +122,7 @@ class PostponedArgumentsAnalyzer( c.canBeProper(rawReturnType) -> substitute(rawReturnType) // For Unit-coercion - c.hasUpperOrEqualUnitConstraint(rawReturnType) && !c.hasEqualNothingConstraint(rawReturnType) -> builtIns.unitType + c.hasUpperOrEqualUnitConstraint(rawReturnType) -> builtIns.unitType else -> null } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt index 5f427d3b707..63d31ab71c2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilder.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.calls.inference import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer +import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument @@ -62,9 +63,30 @@ fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible( lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition +): Boolean = + addConstraintIfCompatible(lowerType, upperType, position, ConstraintKind.LOWER) + +fun ConstraintSystemBuilder.addEqualityConstraintIfCompatible( + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, + position: ConstraintPosition +): Boolean = + addConstraintIfCompatible(lowerType, upperType, position, ConstraintKind.EQUALITY) + +private fun ConstraintSystemBuilder.addConstraintIfCompatible( + lowerType: KotlinTypeMarker, + upperType: KotlinTypeMarker, + position: ConstraintPosition, + kind: ConstraintKind ) = runTransaction { - if (!hasContradiction) addSubtypeConstraint(lowerType, upperType, position) + if (!hasContradiction) { + when (kind) { + ConstraintKind.LOWER -> addSubtypeConstraint(lowerType, upperType, position) + ConstraintKind.UPPER -> addSubtypeConstraint(upperType, lowerType, position) + ConstraintKind.EQUALITY -> addEqualityConstraint(lowerType, upperType, position) + } + } !hasContradiction } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index e222993d602..103a8b129b0 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -389,10 +389,4 @@ class NewConstraintSystemImpl( val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() } } - - override fun hasEqualNothingConstraint(type: KotlinTypeMarker): Boolean { - checkState(State.BUILDING, State.COMPLETION, State.FREEZED) - val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false - return constraints.any { (it.kind == ConstraintKind.EQUALITY) && it.type.isNothing() } - } } diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt index c86551c0788..313b0300703 100644 --- a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithExpectedTypeAndBound.kt @@ -3,11 +3,11 @@ fun materializeNumber(): T = TODO() fun a(): Unit = run { - materializeNumber() + materializeNumber() } fun b(): Unit = run { run { - materializeNumber() + materializeNumber() } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt new file mode 100644 index 00000000000..1d5333bbba1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Base +class Foo : Base + +fun myRun(action: () -> T): T = action() + +fun foo(f: (Foo) -> Unit) {} + +fun main() { + foo { f: Foo -> + myRun { f } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt new file mode 100644 index 00000000000..3b39cfa6822 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.txt @@ -0,0 +1,18 @@ +package + +public fun foo(/*0*/ f: (Foo) -> kotlin.Unit): kotlin.Unit +public fun main(): kotlin.Unit +public fun myRun(/*0*/ action: () -> T): T + +public interface Base { + 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 +} + +public final class Foo : Base { + public constructor Foo() + 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/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index b2b1c7e7ca1..078257a5caf 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10671,6 +10671,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index a1ac0ebb72a..816d37e6b90 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10666,6 +10666,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coerctionToUnitForATypeWithUpperBound.kt") + public void testCoerctionToUnitForATypeWithUpperBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coerctionToUnitForATypeWithUpperBound.kt"); + } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");