[NI] Discriminate integer literal types as they are less specific

Plus simplify code in `ResultTypeResolver` a bit
This commit is contained in:
Mikhail Zarechenskiy
2019-03-26 11:07:20 +03:00
parent e01cac4c3d
commit a50cc99b01
7 changed files with 61 additions and 16 deletions
@@ -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");
@@ -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
}
@@ -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");
@@ -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");