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 fe3b9bffc04..8f6e9ade851 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -23463,6 +23463,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/varargs/varargOfNothing.kt"); } + @TestMetadata("varargViewedAsArray.kt") + public void testVarargViewedAsArray() throws Exception { + runTest("compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt"); + } + @TestMetadata("varargsAndFunctionLiterals.kt") public void testVarargsAndFunctionLiterals() throws Exception { runTest("compiler/testData/diagnostics/tests/varargs/varargsAndFunctionLiterals.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt index 6c6055669aa..867413af213 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CallableReferenceResolution.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastI import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.UnwrappedType +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.checker.captureFromExpression import org.jetbrains.kotlin.types.expressions.CoercionStrategy import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes @@ -178,7 +179,8 @@ class CallableReferencesCandidateFactory( candidateDescriptor, dispatchCallableReceiver, extensionCallableReceiver, - expectedType + expectedType, + callComponents.builtIns ) if (defaults != 0 && @@ -224,10 +226,15 @@ class CallableReferencesCandidateFactory( ) } + private enum class VarargMappingState { + UNMAPPED, MAPPED_WITH_PLAIN_ARGS, MAPPED_WITH_ARRAY + } + private fun getArgumentAndReturnTypeUseMappingByExpectedType( descriptor: FunctionDescriptor, expectedType: UnwrappedType?, - unboundReceiverCount: Int + unboundReceiverCount: Int, + builtins: KotlinBuiltIns ): Triple, CoercionStrategy, Int>? { val inputOutputTypes = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType) ?: return null @@ -244,13 +251,29 @@ class CallableReferencesCandidateFactory( * fun foo(a: A, b: B = B(), vararg c: C) */ var defaults = 0 + var varargMappingState = VarargMappingState.UNMAPPED val mappedArguments = arrayOfNulls(fakeArguments.size) + for ((valueParameter, resolvedArgument) in argumentMapping.parameterToCallArgumentMap) { for (fakeArgument in resolvedArgument.arguments) { val index = (fakeArgument as FakeKotlinCallArgumentForCallableReference).index val substitutedParameter = descriptor.valueParameters.getOrNull(valueParameter.index) ?: continue - mappedArguments[index] = substitutedParameter.varargElementType ?: substitutedParameter.type + val mappedArgument: KotlinType? + if (substitutedParameter.isVararg) { + val (varargType, newVarargMappingState) = varargParameterTypeByExpectedParameter( + inputOutputTypes.inputTypes[index], + substitutedParameter, + varargMappingState, + builtins + ) + varargMappingState = newVarargMappingState + mappedArgument = varargType + } else { + mappedArgument = substitutedParameter.type + } + + mappedArguments[index] = mappedArgument } if (resolvedArgument == ResolvedCallArgument.DefaultArgument) defaults++ } @@ -265,11 +288,42 @@ class CallableReferencesCandidateFactory( return Triple(mappedArguments as Array, coercion, defaults) } + private fun varargParameterTypeByExpectedParameter( + expectedParameterType: KotlinType, + substitutedParameter: ValueParameterDescriptor, + varargMappingState: VarargMappingState, + builtins: KotlinBuiltIns + ): Pair { + val elementType = substitutedParameter.varargElementType + ?: error("Vararg parameter $substitutedParameter does not have vararg type") + + return when (varargMappingState) { + VarargMappingState.UNMAPPED -> { + if (KotlinBuiltIns.isArrayOrPrimitiveArray(expectedParameterType)) { + val arrayType = builtins.getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(elementType) + ?: builtins.getArrayType(Variance.OUT_VARIANCE, elementType) + arrayType to VarargMappingState.MAPPED_WITH_ARRAY + } else { + elementType to VarargMappingState.MAPPED_WITH_PLAIN_ARGS + } + } + VarargMappingState.MAPPED_WITH_PLAIN_ARGS -> { + if (KotlinBuiltIns.isArrayOrPrimitiveArray(expectedParameterType)) + null to VarargMappingState.MAPPED_WITH_PLAIN_ARGS + else + elementType to VarargMappingState.MAPPED_WITH_PLAIN_ARGS + } + VarargMappingState.MAPPED_WITH_ARRAY -> + null to VarargMappingState.MAPPED_WITH_ARRAY + } + } + private fun buildReflectionType( descriptor: CallableDescriptor, dispatchReceiver: CallableReceiver?, extensionReceiver: CallableReceiver?, - expectedType: UnwrappedType? + expectedType: UnwrappedType?, + builtins: KotlinBuiltIns ): Pair { val argumentsAndReceivers = ArrayList(descriptor.valueParameters.size + 2) @@ -281,7 +335,7 @@ class CallableReferencesCandidateFactory( } val descriptorReturnType = descriptor.returnType - ?: ErrorUtils.createErrorType("Error return type for descriptor: $descriptor") + ?: ErrorUtils.createErrorType("Error return type for descriptor: $descriptor") when (descriptor) { is PropertyDescriptor -> { @@ -305,7 +359,8 @@ class CallableReferencesCandidateFactory( val defaults: Int val argumentsAndExpectedTypeCoercion = getArgumentAndReturnTypeUseMappingByExpectedType( descriptor, expectedType, - unboundReceiverCount = argumentsAndReceivers.size + unboundReceiverCount = argumentsAndReceivers.size, + builtins = builtins ) if (argumentsAndExpectedTypeCoercion == null) { diff --git a/compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt b/compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt new file mode 100644 index 00000000000..8c9839b753c --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +NewInference +// DONT_RUN_GENERATED_CODE: JS + +fun sum(vararg args: Int): Int { + var result = 0 + for (arg in args) + result += arg + return result +} + +fun nsum(vararg args: Number) = sum(*IntArray(args.size) { args[it].toInt() }) + +fun usePlainArgs(fn: (Int, Int) -> Int) = fn(1, 1) +fun usePrimitiveArray(fn: (IntArray) -> Int) = fn(intArrayOf(1, 1, 1)) +fun useArray(fn: (Array) -> Int) = fn(arrayOf(1, 1, 1, 1)) + +fun box(): String { + var result = usePlainArgs(::sum) + if (result != 2) + return "Fail: plain args $result != 2" + result = usePrimitiveArray(::sum) + if (result != 3) + return "Fail: primitive array $result != 3" + result = useArray(::nsum) + if (result != 4) + return "Fail: reference array $result != 4" + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callableReferenceOnExpectFun.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callableReferenceOnExpectFun.kt index 0acf67cc457..0c22e4752ef 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callableReferenceOnExpectFun.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/callableReferenceOnExpectFun.kt @@ -1,4 +1,3 @@ -// !WITH_NEW_INFERENCE // !LANGUAGE: +MultiPlatformProjects // MODULE: m1-common // FILE: common.kt @@ -10,7 +9,7 @@ expect fun foo(): String fun g(f: () -> String): String = f() fun test() { - g(::foo) + g(::foo) } // MODULE: m2-jvm(m1-common) diff --git a/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt b/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt new file mode 100644 index 00000000000..b9d02d090bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt @@ -0,0 +1,29 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun stringVararg(vararg args: String) {} +fun intVararg(vararg args: Int) {} +fun numberVararg(vararg args: Number) {} + +fun useStrings(fn: (String, String, String) -> Unit) = fn("foo", "bar", "boo") +fun useStringArray(fn: (Array) -> Unit) = fn(arrayOf("foo", "bar", "boo")) + +fun useIntArray(fn: (Array) -> Unit) = fn(arrayOf(1, 2, 3)) +fun usePrimitiveIntArray(fn: (IntArray) -> Unit) = fn(intArrayOf(4, 5, 6)) + +fun useMixedStringArgs1(fn: (String, Array) -> Unit) = fn("foo", arrayOf("bar", "baz")) +fun useMixedStringArgs2(fn: (Array, String) -> Unit) = fn(arrayOf("foo", "bar"), "baz") +fun useMixedStringArgs3(fn: (String, Array, String) -> Unit) = fn("foo", arrayOf("bar", "baz"), "boo") +fun useTwoStringArrays(fn: (Array, Array) -> Unit) = fn(arrayOf("foo", "bar"), arrayOf("baz", "boo")) + +fun test() { + useStrings(::stringVararg) + useStringArray(::stringVararg) + useIntArray(::numberVararg) + usePrimitiveIntArray(::intVararg) + useIntArray() -> Unit", "KFunction1")!>::intVararg) + useMixedStringArgs1() -> Unit", "KFunction1, Unit>")!>::stringVararg) + useMixedStringArgs2(, String) -> Unit", "KFunction1, Unit>")!>::stringVararg) + useMixedStringArgs3(, String) -> Unit", "KFunction1, Unit>")!>::stringVararg) + useTwoStringArrays(, Array) -> Unit", "KFunction1, Unit>")!>::stringVararg) +} diff --git a/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.txt b/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.txt new file mode 100644 index 00000000000..19bfbb853c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.txt @@ -0,0 +1,14 @@ +package + +public fun intVararg(/*0*/ vararg args: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit +public fun numberVararg(/*0*/ vararg args: kotlin.Number /*kotlin.Array*/): kotlin.Unit +public fun stringVararg(/*0*/ vararg args: kotlin.String /*kotlin.Array*/): kotlin.Unit +public fun test(): kotlin.Unit +public fun useIntArray(/*0*/ fn: (kotlin.Array) -> kotlin.Unit): kotlin.Unit +public fun useMixedStringArgs1(/*0*/ fn: (kotlin.String, kotlin.Array) -> kotlin.Unit): kotlin.Unit +public fun useMixedStringArgs2(/*0*/ fn: (kotlin.Array, kotlin.String) -> kotlin.Unit): kotlin.Unit +public fun useMixedStringArgs3(/*0*/ fn: (kotlin.String, kotlin.Array, kotlin.String) -> kotlin.Unit): kotlin.Unit +public fun usePrimitiveIntArray(/*0*/ fn: (kotlin.IntArray) -> kotlin.Unit): kotlin.Unit +public fun useStringArray(/*0*/ fn: (kotlin.Array) -> kotlin.Unit): kotlin.Unit +public fun useStrings(/*0*/ fn: (kotlin.String, kotlin.String, kotlin.String) -> kotlin.Unit): kotlin.Unit +public fun useTwoStringArrays(/*0*/ fn: (kotlin.Array, kotlin.Array) -> kotlin.Unit): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 712c4c266d8..fb4d44f1f72 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -23545,6 +23545,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/varargs/varargOfNothing.kt"); } + @TestMetadata("varargViewedAsArray.kt") + public void testVarargViewedAsArray() throws Exception { + runTest("compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt"); + } + @TestMetadata("varargsAndFunctionLiterals.kt") public void testVarargsAndFunctionLiterals() throws Exception { runTest("compiler/testData/diagnostics/tests/varargs/varargsAndFunctionLiterals.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 51c13a242ea..0d47b33225e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -23465,6 +23465,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/varargs/varargOfNothing.kt"); } + @TestMetadata("varargViewedAsArray.kt") + public void testVarargViewedAsArray() throws Exception { + runTest("compiler/testData/diagnostics/tests/varargs/varargViewedAsArray.kt"); + } + @TestMetadata("varargsAndFunctionLiterals.kt") public void testVarargsAndFunctionLiterals() throws Exception { runTest("compiler/testData/diagnostics/tests/varargs/varargsAndFunctionLiterals.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b45888afd45..e58979ea11f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -2697,6 +2697,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsArray.kt"); } + @TestMetadata("varargViewedAsPrimitiveArray.kt") + public void testVarargViewedAsPrimitiveArray() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt"); + } + @TestMetadata("varargWithDefaultValue.kt") public void testVarargWithDefaultValue() throws Exception { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargWithDefaultValue.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a455ea6d3a4..7f9bda635f5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -2697,6 +2697,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsArray.kt"); } + @TestMetadata("varargViewedAsPrimitiveArray.kt") + public void testVarargViewedAsPrimitiveArray() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt"); + } + @TestMetadata("varargWithDefaultValue.kt") public void testVarargWithDefaultValue() throws Exception { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargWithDefaultValue.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 32bd54b6234..5320ace7ca8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -2677,6 +2677,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsArray.kt"); } + @TestMetadata("varargViewedAsPrimitiveArray.kt") + public void testVarargViewedAsPrimitiveArray() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt"); + } + @TestMetadata("varargWithDefaultValue.kt") public void testVarargWithDefaultValue() throws Exception { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargWithDefaultValue.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 6369d92f292..cb935863069 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -2127,6 +2127,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsArray.kt"); } + @TestMetadata("varargViewedAsPrimitiveArray.kt") + public void testVarargViewedAsPrimitiveArray() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt"); + } + @TestMetadata("varargWithDefaultValue.kt") public void testVarargWithDefaultValue() throws Exception { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargWithDefaultValue.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 872ad68ec0d..9330cc95bc2 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -2127,6 +2127,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsArray.kt"); } + @TestMetadata("varargViewedAsPrimitiveArray.kt") + public void testVarargViewedAsPrimitiveArray() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargViewedAsPrimitiveArray.kt"); + } + @TestMetadata("varargWithDefaultValue.kt") public void testVarargWithDefaultValue() throws Exception { runTest("compiler/testData/codegen/box/callableReference/varargAndDefaults/varargWithDefaultValue.kt");