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
This commit is contained in:
Mikhail Zarechenskiy
2020-06-26 05:39:10 +03:00
parent c5a2ab2512
commit c2c139ef4f
10 changed files with 92 additions and 3 deletions

View File

@@ -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");

View File

@@ -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<FakeKotlinCallArgumentForCallableReference> {
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,

View File

@@ -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(

View File

@@ -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"
}

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");

View File

@@ -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");