Fix coercion to Unit when variable already have other constraints
Don't add `Unit` if variable has an upper constraint T <: A. It's impossible to coerce variable T to Unit as constraint system will be always contradictory: T := Unit => Unit should be subtype of A #KT-39900 Fixed
This commit is contained in:
+5
@@ -10664,6 +10664,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt");
|
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")
|
@TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt")
|
||||||
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
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
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode
|
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle
|
import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle
|
||||||
@@ -285,7 +285,7 @@ class KotlinCallCompleter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
expectedType === TypeUtils.UNIT_EXPECTED_TYPE ->
|
expectedType === TypeUtils.UNIT_EXPECTED_TYPE ->
|
||||||
csBuilder.addSubtypeConstraintIfCompatible(
|
csBuilder.addEqualityConstraintIfCompatible(
|
||||||
returnType, csBuilder.builtIns.unitType, ExpectedTypeConstraintPosition(resolvedCall.atom)
|
returnType, csBuilder.builtIns.unitType, ExpectedTypeConstraintPosition(resolvedCall.atom)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -35,7 +35,6 @@ class PostponedArgumentsAnalyzer(
|
|||||||
fun canBeProper(type: KotlinTypeMarker): Boolean
|
fun canBeProper(type: KotlinTypeMarker): Boolean
|
||||||
|
|
||||||
fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean
|
fun hasUpperOrEqualUnitConstraint(type: KotlinTypeMarker): Boolean
|
||||||
fun hasEqualNothingConstraint(type: KotlinTypeMarker): Boolean
|
|
||||||
|
|
||||||
// mutable operations
|
// mutable operations
|
||||||
fun addOtherSystem(otherSystem: ConstraintStorage)
|
fun addOtherSystem(otherSystem: ConstraintStorage)
|
||||||
@@ -123,7 +122,7 @@ class PostponedArgumentsAnalyzer(
|
|||||||
c.canBeProper(rawReturnType) -> substitute(rawReturnType)
|
c.canBeProper(rawReturnType) -> substitute(rawReturnType)
|
||||||
|
|
||||||
// For Unit-coercion
|
// For Unit-coercion
|
||||||
c.hasUpperOrEqualUnitConstraint(rawReturnType) && !c.hasEqualNothingConstraint(rawReturnType) -> builtIns.unitType
|
c.hasUpperOrEqualUnitConstraint(rawReturnType) -> builtIns.unitType
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.inference
|
package org.jetbrains.kotlin.resolve.calls.inference
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
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.ConstraintPosition
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument
|
||||||
@@ -62,9 +63,30 @@ fun ConstraintSystemBuilder.addSubtypeConstraintIfCompatible(
|
|||||||
lowerType: KotlinTypeMarker,
|
lowerType: KotlinTypeMarker,
|
||||||
upperType: KotlinTypeMarker,
|
upperType: KotlinTypeMarker,
|
||||||
position: ConstraintPosition
|
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 {
|
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
|
!hasContradiction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-6
@@ -389,10 +389,4 @@ class NewConstraintSystemImpl(
|
|||||||
val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false
|
val constraints = storage.notFixedTypeVariables[type.typeConstructor()]?.constraints ?: return false
|
||||||
return constraints.any { (it.kind == ConstraintKind.UPPER || it.kind == ConstraintKind.EQUALITY) && it.type.isUnit() }
|
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() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -3,11 +3,11 @@
|
|||||||
fun <T : Number> materializeNumber(): T = TODO()
|
fun <T : Number> materializeNumber(): T = TODO()
|
||||||
|
|
||||||
fun a(): Unit = run {
|
fun a(): Unit = run {
|
||||||
<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>()
|
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun b(): Unit = run {
|
fun b(): Unit = run {
|
||||||
run {
|
run {
|
||||||
<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>()
|
<!NI;NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>materializeNumber<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
interface Base
|
||||||
|
class Foo : Base
|
||||||
|
|
||||||
|
fun <T : Base> myRun(action: () -> T): T = action()
|
||||||
|
|
||||||
|
fun foo(f: (Foo) -> Unit) {}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
foo { f: Foo ->
|
||||||
|
myRun { f }
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ f: (Foo) -> kotlin.Unit): kotlin.Unit
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
public fun </*0*/ T : Base> 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
|
||||||
|
}
|
||||||
@@ -10671,6 +10671,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt");
|
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")
|
@TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt")
|
||||||
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
||||||
|
|||||||
Generated
+5
@@ -10666,6 +10666,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt");
|
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")
|
@TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt")
|
||||||
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user