[NI] Discriminate integer literal types as they are less specific
Plus simplify code in `ResultTypeResolver` a bit
This commit is contained in:
+5
@@ -14120,6 +14120,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/intValuesOutOfRange.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numberAsUnionAndIntersection.kt")
|
||||
public void testNumberAsUnionAndIntersection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numbersInSimpleConstraints.kt")
|
||||
public void testNumbersInSimpleConstraints() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt");
|
||||
|
||||
+3
-1
@@ -81,7 +81,9 @@ object NewCommonSuperTypeCalculator {
|
||||
private fun List<SimpleType>.uniquify(): List<SimpleType> {
|
||||
val uniqueTypes = arrayListOf<SimpleType>()
|
||||
for (type in this) {
|
||||
val isNewUniqueType = uniqueTypes.all { !NewKotlinTypeChecker.equalTypes(it, type) }
|
||||
val isNewUniqueType = uniqueTypes.all {
|
||||
!NewKotlinTypeChecker.equalTypes(it, type) || it.constructor is IntegerLiteralTypeConstructor
|
||||
}
|
||||
if (isNewUniqueType) {
|
||||
uniqueTypes += type
|
||||
}
|
||||
|
||||
+15
-15
@@ -18,9 +18,11 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator.ResolveDirection
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.checkConstraint
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.intersectTypes
|
||||
|
||||
@@ -42,7 +44,7 @@ class ResultTypeResolver(
|
||||
}
|
||||
|
||||
fun findResultTypeOrNull(c: Context, variableWithConstraints: VariableWithConstraints, direction: ResolveDirection): UnwrappedType? {
|
||||
findResultIfThereIsEqualsConstraint(c, variableWithConstraints, allowedFixToNotProperType = false)?.let { return it }
|
||||
findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it }
|
||||
|
||||
val subType = findSubType(c, variableWithConstraints)
|
||||
val superType = findSuperType(c, variableWithConstraints)
|
||||
@@ -123,24 +125,22 @@ class ResultTypeResolver(
|
||||
return null
|
||||
}
|
||||
|
||||
fun findResultIfThereIsEqualsConstraint(
|
||||
c: Context,
|
||||
variableWithConstraints: VariableWithConstraints,
|
||||
allowedFixToNotProperType: Boolean = false
|
||||
): UnwrappedType? {
|
||||
val properEqualsConstraint = variableWithConstraints.constraints.filter {
|
||||
fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): UnwrappedType? {
|
||||
val properEqualityConstraints = variableWithConstraints.constraints.filter {
|
||||
it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type)
|
||||
}
|
||||
|
||||
if (properEqualsConstraint.isNotEmpty()) {
|
||||
return properEqualsConstraint.map { it.type }.singleBestRepresentative()?.unwrap()
|
||||
?: properEqualsConstraint.first().type // seems like constraint system has contradiction
|
||||
}
|
||||
if (!allowedFixToNotProperType) return null
|
||||
return representativeFromEqualityConstraints(properEqualityConstraints)
|
||||
}
|
||||
|
||||
val notProperEqualsConstraint = variableWithConstraints.constraints.filter { it.kind == ConstraintKind.EQUALITY }
|
||||
// Discriminate integer literal types as they are less specific than separate integer types (Int, Short...)
|
||||
private fun representativeFromEqualityConstraints(constraints: List<Constraint>): UnwrappedType? {
|
||||
if (constraints.isEmpty()) return null
|
||||
|
||||
// may be we should just firstOrNull
|
||||
return notProperEqualsConstraint.singleOrNull()?.type
|
||||
val constraintTypes = constraints.map { it.type }
|
||||
val nonLiteralTypes = constraintTypes.filter { it.constructor !is IntegerLiteralTypeConstructor }
|
||||
return nonLiteralTypes.singleBestRepresentative()?.unwrap()
|
||||
?: constraintTypes.singleBestRepresentative()?.unwrap()
|
||||
?: constraintTypes.first() // seems like constraint system has contradiction
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun test(numbers: List<Number>) {
|
||||
|
||||
// Short <: R, ILT <: R => CST(Short, ILT) = Short
|
||||
// => we should pick Short in such situation as it more specific
|
||||
shortExpected { getShort() ?: 1 }
|
||||
|
||||
// Short <: R, ILT <: R, R <: Comparable<R> =>
|
||||
// Short <: Comparable<R>, ILT <: Comparable<R> =>
|
||||
// Comparable<Short> <: Comparable<R>, Comparable<ILT> <: Comparable<R> =>
|
||||
// R <: Short, R <: ILT =>
|
||||
// R := Short, R := ILT
|
||||
// => we should pick Short as it more specific
|
||||
shortComparable { getShort() ?: 1 }
|
||||
}
|
||||
|
||||
fun <R> shortExpected(f: () -> R) {}
|
||||
fun <R : Comparable<R>> shortComparable(f: () -> R) {}
|
||||
|
||||
fun getShort(): Short? = 1
|
||||
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun getShort(): kotlin.Short?
|
||||
public fun </*0*/ R : kotlin.Comparable<R>> shortComparable(/*0*/ f: () -> R): kotlin.Unit
|
||||
public fun </*0*/ R> shortExpected(/*0*/ f: () -> R): kotlin.Unit
|
||||
public fun test(/*0*/ numbers: kotlin.collections.List<kotlin.Number>): kotlin.Unit
|
||||
@@ -14127,6 +14127,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/intValuesOutOfRange.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numberAsUnionAndIntersection.kt")
|
||||
public void testNumberAsUnionAndIntersection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numbersInSimpleConstraints.kt")
|
||||
public void testNumbersInSimpleConstraints() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt");
|
||||
|
||||
Generated
+5
@@ -14122,6 +14122,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/intValuesOutOfRange.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numberAsUnionAndIntersection.kt")
|
||||
public void testNumberAsUnionAndIntersection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("numbersInSimpleConstraints.kt")
|
||||
public void testNumbersInSimpleConstraints() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt");
|
||||
|
||||
Reference in New Issue
Block a user