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");
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
+2
-2
@@ -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)
|
||||
)
|
||||
|
||||
|
||||
+1
-2
@@ -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
|
||||
}
|
||||
|
||||
+23
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
-6
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -3,11 +3,11 @@
|
||||
fun <T : Number> materializeNumber(): T = TODO()
|
||||
|
||||
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 {
|
||||
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");
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user