From c2c139ef4f957a9723a6fa97ebd9c29a0a9d847e Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 26 Jun 2020 05:39:10 +0300 Subject: [PATCH] Fix adaptation for references with default values after varargs After vararg argument it's possible to pass values only by name, so here we modulate this behavior #KT-37721 Fixed --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../components/CallableReferenceResolution.kt | 32 ++++++++++++++++++- .../resolve/calls/model/ArgumentsImpl.kt | 5 +-- .../referenceToVarargWithDefaults.kt | 23 +++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 10 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index b74aefcc2f5..2b21bbf2f85 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -2090,6 +2090,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.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 caf4dab89d5..1220fa17d82 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 @@ -292,7 +292,7 @@ class CallableReferencesCandidateFactory( val expectedArgumentCount = inputOutputTypes.inputTypes.size - unboundReceiverCount if (expectedArgumentCount < 0) return null - val fakeArguments = (0 until expectedArgumentCount).map { FakeKotlinCallArgumentForCallableReference(it) } + val fakeArguments = createFakeArgumentsForReference(descriptor, expectedArgumentCount, inputOutputTypes, unboundReceiverCount) val argumentMapping = callComponents.argumentsToParametersMapper.mapArguments(fakeArguments, externalArgument = null, descriptor = descriptor) if (argumentMapping.diagnostics.any { !it.candidateApplicability.isSuccess }) return null @@ -387,6 +387,36 @@ class CallableReferencesCandidateFactory( ) } + private fun createFakeArgumentsForReference( + descriptor: FunctionDescriptor, + expectedArgumentCount: Int, + inputOutputTypes: InputOutputTypes, + unboundReceiverCount: Int + ): List { + var afterVararg = false + var varargComponentType: UnwrappedType? = null + var vararg = false + return (0 until expectedArgumentCount).map { index -> + val inputType = inputOutputTypes.inputTypes.getOrNull(index + unboundReceiverCount) + if (vararg && varargComponentType != inputType) { + afterVararg = true + } + + val valueParameter = descriptor.valueParameters.getOrNull(index) + val name = + if (afterVararg && valueParameter?.declaresDefaultValue() == true) + valueParameter.name + else + null + + if (valueParameter?.isVararg == true) { + varargComponentType = inputType + vararg = true + } + FakeKotlinCallArgumentForCallableReference(index, name) + } + } + private fun varargParameterTypeByExpectedParameter( expectedParameterType: KotlinType, substitutedParameter: ValueParameterDescriptor, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ArgumentsImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ArgumentsImpl.kt index 6745f0b1b33..647df18696d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ArgumentsImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ArgumentsImpl.kt @@ -22,10 +22,11 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.prepareReceiverRegardingCap class FakeKotlinCallArgumentForCallableReference( - val index: Int + val index: Int, + val name: Name? ) : KotlinCallArgument { override val isSpread: Boolean get() = false - override val argumentName: Name? get() = null + override val argumentName: Name? get() = name } class ReceiverExpressionKotlinCallArgument private constructor( diff --git a/compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt b/compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt new file mode 100644 index 00000000000..1197e758f35 --- /dev/null +++ b/compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt @@ -0,0 +1,23 @@ +var result = "fail" + +fun foo(vararg xs: Int, s1: String = "", s2: String = "OK") { + if (xs[0] == 42 && s1 == "good") { + result = s2 + } +} + +fun bar(vararg xs: Int, s: String = "") {} + +fun use(fn: (IntArray, String) -> Unit) { + fn(intArrayOf(42), "good") +} + +fun test() { + use(::foo) + use(::bar) +} + +fun box(): String { + test() + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 425971b4753..49330942b2f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -2110,6 +2110,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b93f8d654c2..d1e66cc9b0c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -2110,6 +2110,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index ea83cc306e6..d8e562b4456 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -2090,6 +2090,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noReflectionForAdaptedCallableReferencesWithSuspendConversion.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("reflectionForVarargAsArray.kt") public void testReflectionForVarargAsArray() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/reflectionForVarargAsArray.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index edf8cf33eea..1c09ade0fdc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -1510,6 +1510,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noNameClashForReferencesToSameFunction.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("simpleDefaultArgument.kt") public void testSimpleDefaultArgument() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/simpleDefaultArgument.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 cb7b12805c7..fffecd4ea31 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 @@ -1520,6 +1520,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noNameClashForReferencesToSameFunction.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("simpleDefaultArgument.kt") public void testSimpleDefaultArgument() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/simpleDefaultArgument.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 6997f7fa23e..078f32c8459 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 @@ -1520,6 +1520,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/noNameClashForReferencesToSameFunction.kt"); } + @TestMetadata("referenceToVarargWithDefaults.kt") + public void testReferenceToVarargWithDefaults() throws Exception { + runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/referenceToVarargWithDefaults.kt"); + } + @TestMetadata("simpleDefaultArgument.kt") public void testSimpleDefaultArgument() throws Exception { runTest("compiler/testData/codegen/box/callableReference/adaptedReferences/simpleDefaultArgument.kt");