NI: Try to solve constraint system with another flexibility from a type variable if couldn't solve
^KT-36254 Fixed
This commit is contained in:
Generated
+10
@@ -16476,6 +16476,16 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariable.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariable() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariableOut.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariableOut() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariableOut.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("genericsAndArrays.kt")
|
@TestMetadata("genericsAndArrays.kt")
|
||||||
public void testGenericsAndArrays() throws Exception {
|
public void testGenericsAndArrays() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@ internal object CreateFreshVariablesSubstitutor : ResolutionPart() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeParameterDescriptor.shouldBeFlexible(): Boolean {
|
fun TypeParameterDescriptor.shouldBeFlexible(): Boolean {
|
||||||
return upperBounds.any {
|
return upperBounds.any {
|
||||||
it.isFlexible() || ((it.constructor.declarationDescriptor as? TypeParameterDescriptor)?.run { shouldBeFlexible() } ?: false)
|
it.isFlexible() || ((it.constructor.declarationDescriptor as? TypeParameterDescriptor)?.run { shouldBeFlexible() } ?: false)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstitutor.shouldBeFlexible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
@@ -27,7 +28,11 @@ class ConstraintIncorporator(
|
|||||||
|
|
||||||
fun getConstraintsForVariable(typeVariable: TypeVariableMarker): Collection<Constraint>
|
fun getConstraintsForVariable(typeVariable: TypeVariableMarker): Collection<Constraint>
|
||||||
|
|
||||||
fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker)
|
fun addNewIncorporatedConstraint(
|
||||||
|
lowerType: KotlinTypeMarker,
|
||||||
|
upperType: KotlinTypeMarker,
|
||||||
|
shouldTryUseDifferentFlexibilityForUpperType: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext)
|
fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext)
|
||||||
}
|
}
|
||||||
@@ -49,11 +54,14 @@ class ConstraintIncorporator(
|
|||||||
typeVariable: TypeVariableMarker,
|
typeVariable: TypeVariableMarker,
|
||||||
constraint: Constraint
|
constraint: Constraint
|
||||||
) {
|
) {
|
||||||
|
val shouldBeTypeVariableFlexible =
|
||||||
|
typeVariable is TypeVariableFromCallableDescriptor && typeVariable.originalTypeParameter.shouldBeFlexible()
|
||||||
|
|
||||||
// \alpha <: constraint.type
|
// \alpha <: constraint.type
|
||||||
if (constraint.kind != ConstraintKind.LOWER) {
|
if (constraint.kind != ConstraintKind.LOWER) {
|
||||||
getConstraintsForVariable(typeVariable).forEach {
|
getConstraintsForVariable(typeVariable).forEach {
|
||||||
if (it.kind != ConstraintKind.UPPER) {
|
if (it.kind != ConstraintKind.UPPER) {
|
||||||
addNewIncorporatedConstraint(it.type, constraint.type)
|
addNewIncorporatedConstraint(it.type, constraint.type, shouldBeTypeVariableFlexible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +70,7 @@ class ConstraintIncorporator(
|
|||||||
if (constraint.kind != ConstraintKind.UPPER) {
|
if (constraint.kind != ConstraintKind.UPPER) {
|
||||||
getConstraintsForVariable(typeVariable).forEach {
|
getConstraintsForVariable(typeVariable).forEach {
|
||||||
if (it.kind != ConstraintKind.LOWER) {
|
if (it.kind != ConstraintKind.LOWER) {
|
||||||
addNewIncorporatedConstraint(constraint.type, it.type)
|
addNewIncorporatedConstraint(constraint.type, it.type, shouldBeTypeVariableFlexible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-5
@@ -148,10 +148,33 @@ class ConstraintInjector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runIsSubtypeOf(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
|
fun runIsSubtypeOf(
|
||||||
if (!AbstractTypeChecker.isSubtypeOf(this@TypeCheckerContext as AbstractTypeCheckerContext, lowerType, upperType)) {
|
lowerType: KotlinTypeMarker,
|
||||||
|
upperType: KotlinTypeMarker,
|
||||||
|
shouldTryUseDifferentFlexibilityForUpperType: Boolean = false
|
||||||
|
) {
|
||||||
|
fun isSubtypeOf(upperType: KotlinTypeMarker) =
|
||||||
|
AbstractTypeChecker.isSubtypeOf(
|
||||||
|
this@TypeCheckerContext as AbstractTypeCheckerContext,
|
||||||
|
lowerType,
|
||||||
|
upperType
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!isSubtypeOf(upperType)) {
|
||||||
// todo improve error reporting -- add information about base types
|
// todo improve error reporting -- add information about base types
|
||||||
c.addError(NewConstraintError(lowerType, upperType, position))
|
if (shouldTryUseDifferentFlexibilityForUpperType && upperType is SimpleType) {
|
||||||
|
/*
|
||||||
|
* Please don't reuse this logic.
|
||||||
|
* It's necessary to solve constraint systems when flexibility isn't propagated through a type variable.
|
||||||
|
* It's OK in the old inference because it uses already substituted types, that are with the correct flexibility.
|
||||||
|
*/
|
||||||
|
val flexibleUpperType = createFlexibleType(upperType, upperType.withNullability(true))
|
||||||
|
if (!isSubtypeOf(flexibleUpperType)) {
|
||||||
|
c.addError(NewConstraintError(lowerType, flexibleUpperType, position))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.addError(NewConstraintError(lowerType, upperType, position))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,10 +204,14 @@ class ConstraintInjector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from ConstraintIncorporator.Context
|
// from ConstraintIncorporator.Context
|
||||||
override fun addNewIncorporatedConstraint(lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker) {
|
override fun addNewIncorporatedConstraint(
|
||||||
|
lowerType: KotlinTypeMarker,
|
||||||
|
upperType: KotlinTypeMarker,
|
||||||
|
shouldTryUseDifferentFlexibilityForUpperType: Boolean
|
||||||
|
) {
|
||||||
if (lowerType === upperType) return
|
if (lowerType === upperType) return
|
||||||
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
||||||
runIsSubtypeOf(lowerType, upperType)
|
runIsSubtypeOf(lowerType, upperType, shouldTryUseDifferentFlexibilityForUpperType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
// Issue: KT-36254
|
||||||
|
|
||||||
|
// FILE: Convertor.java
|
||||||
|
|
||||||
|
public interface Convertor<Src, Dst> {
|
||||||
|
Dst convert(Src o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun takeConvertor(c: Convertor<String, String>) {}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
takeConvertor(Convertor { null })
|
||||||
|
}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
public fun takeConvertor(/*0*/ c: Convertor<kotlin.String, kotlin.String>): kotlin.Unit
|
||||||
|
|
||||||
|
public interface Convertor</*0*/ Src : kotlin.Any!, /*1*/ Dst : kotlin.Any!> {
|
||||||
|
public abstract fun convert(/*0*/ o: Src!): Dst!
|
||||||
|
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
|
||||||
|
}
|
||||||
Vendored
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
// Issue: KT-36254
|
||||||
|
|
||||||
|
// FILE: Convertor.java
|
||||||
|
|
||||||
|
public interface Convertor<Src, Dst> {
|
||||||
|
Out<Dst> convert(Out<Src> o);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun takeConvertor(c: Convertor<String, String>) {}
|
||||||
|
|
||||||
|
class Out<out T> {}
|
||||||
|
|
||||||
|
fun main(o: Out<Nothing?>) {
|
||||||
|
takeConvertor(Convertor { o })
|
||||||
|
}
|
||||||
Vendored
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ o: Out<kotlin.Nothing?>): kotlin.Unit
|
||||||
|
public fun takeConvertor(/*0*/ c: Convertor<kotlin.String, kotlin.String>): kotlin.Unit
|
||||||
|
|
||||||
|
public interface Convertor</*0*/ Src : kotlin.Any!, /*1*/ Dst : kotlin.Any!> {
|
||||||
|
public abstract fun convert(/*0*/ o: Out<Src!>!): Out<Dst!>!
|
||||||
|
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 Out</*0*/ out T> {
|
||||||
|
public constructor Out</*0*/ out T>()
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -16483,6 +16483,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariable.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariable() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariableOut.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariableOut() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariableOut.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("genericsAndArrays.kt")
|
@TestMetadata("genericsAndArrays.kt")
|
||||||
public void testGenericsAndArrays() throws Exception {
|
public void testGenericsAndArrays() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
||||||
|
|||||||
Generated
+10
@@ -16478,6 +16478,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/entrySet.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariable.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariable() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("flexibilityThroughTypeVariableOut.kt")
|
||||||
|
public void testFlexibilityThroughTypeVariableOut() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/flexibilityThroughTypeVariableOut.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("genericsAndArrays.kt")
|
@TestMetadata("genericsAndArrays.kt")
|
||||||
public void testGenericsAndArrays() throws Exception {
|
public void testGenericsAndArrays() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
runTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/genericsAndArrays.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user