diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 9aacd68bbf5..ff572170599 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -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"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt index 2d20545fb47..aa682bbc0a8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/NewCommonSuperTypeCalculator.kt @@ -81,7 +81,9 @@ object NewCommonSuperTypeCalculator { private fun List.uniquify(): List { val uniqueTypes = arrayListOf() 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 } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 62972a7f284..59c4d6105f2 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -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): 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 } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt b/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt new file mode 100644 index 00000000000..4d9df23ad57 --- /dev/null +++ b/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(numbers: List) { + + // 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 => + // Short <: Comparable, ILT <: Comparable => + // Comparable <: Comparable, Comparable <: Comparable => + // R <: Short, R <: ILT => + // R := Short, R := ILT + // => we should pick Short as it more specific + shortComparable { getShort() ?: 1 } +} + +fun shortExpected(f: () -> R) {} +fun > shortComparable(f: () -> R) {} + +fun getShort(): Short? = 1 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.txt b/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.txt new file mode 100644 index 00000000000..0c96082adcd --- /dev/null +++ b/compiler/testData/diagnostics/tests/numbers/numberAsUnionAndIntersection.txt @@ -0,0 +1,6 @@ +package + +public fun getShort(): kotlin.Short? +public fun > shortComparable(/*0*/ f: () -> R): kotlin.Unit +public fun shortExpected(/*0*/ f: () -> R): kotlin.Unit +public fun test(/*0*/ numbers: kotlin.collections.List): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 34b016ad086..2d4eb02f5e0 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 1ea274dc59d..17d5a3063cd 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -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");