Skip to content

Commit ecec87c

Browse files
committed
Refine signature calculation for methods with default parameters
The problem was that he number of mask parameters for defaults when generating methods declaration was being calculated upon resulting signature (with additional parameters: extension receivers, enum name/ordinal), while on call-sites the masks number was calculated by the arguments number in resolved call, i.e. by the number of real value parameters. And because of the additional synthetic parameters (like enum.ordinal) these two numbers could be different. The solution is just to use value parameters number in both places. Note, that we only count value parameters from the original sourse declaration, ignoring synthetic ones generated by backend (e.g. Continuation for suspend functions) #KT-14565 Fixed
1 parent 9e03b71 commit ecec87c

File tree

12 files changed

+343
-14
lines changed

12 files changed

+343
-14
lines changed

compiler/backend/src/org/jetbrains/kotlin/codegen/ArgumentGenerator.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.jetbrains.kotlin.codegen
1818

19+
import org.jetbrains.kotlin.descriptors.CallableDescriptor
1920
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
2021
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
2122
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
@@ -31,7 +32,12 @@ abstract class ArgumentGenerator {
3132
*
3233
* @see kotlin.reflect.jvm.internal.KCallableImpl.callBy
3334
*/
34-
open fun generate(valueArgumentsByIndex: List<ResolvedValueArgument>, actualArgs: List<ResolvedValueArgument>): DefaultCallArgs {
35+
open fun generate(
36+
valueArgumentsByIndex: List<ResolvedValueArgument>,
37+
actualArgs: List<ResolvedValueArgument>,
38+
// may be null for a constructor of an object literal
39+
calleeDescriptor: CallableDescriptor?
40+
): DefaultCallArgs {
3541
assert(valueArgumentsByIndex.size == actualArgs.size) {
3642
"Value arguments collection should have same size, but ${valueArgumentsByIndex.size} != ${actualArgs.size}"
3743
}
@@ -48,7 +54,8 @@ abstract class ArgumentGenerator {
4854
}
4955
}
5056

51-
val defaultArgs = DefaultCallArgs(valueArgumentsByIndex.size)
57+
// Use unwrapped version, because additional synthetic parameters can't have default values
58+
val defaultArgs = DefaultCallArgs(calleeDescriptor?.unwrapFrontendVersion()?.valueParameters?.size ?: 0)
5259

5360
for (argumentWithDeclIndex in actualArgsWithDeclIndex) {
5461
val argument = argumentWithDeclIndex.arg

compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.jetbrains.kotlin.codegen;
1818

1919
import org.jetbrains.annotations.NotNull;
20+
import org.jetbrains.annotations.Nullable;
21+
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
2022
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
2123
import org.jetbrains.kotlin.psi.KtExpression;
2224
import org.jetbrains.kotlin.psi.ValueArgument;
@@ -54,11 +56,12 @@ public CallBasedArgumentGenerator(
5456
@Override
5557
public DefaultCallArgs generate(
5658
@NotNull List<? extends ResolvedValueArgument> valueArgumentsByIndex,
57-
@NotNull List<? extends ResolvedValueArgument> valueArgs
59+
@NotNull List<? extends ResolvedValueArgument> valueArgs,
60+
@Nullable CallableDescriptor calleeDescriptor
5861
) {
5962
boolean shouldMarkLineNumbers = this.codegen.isShouldMarkLineNumbers();
6063
this.codegen.setShouldMarkLineNumbers(false);
61-
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs);
64+
DefaultCallArgs defaultArgs = super.generate(valueArgumentsByIndex, valueArgs, calleeDescriptor);
6265
this.codegen.setShouldMarkLineNumbers(shouldMarkLineNumbers);
6366
return defaultArgs;
6467
}

compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,7 +1709,7 @@ public Unit invoke(InstructionAdapter v) {
17091709
ArgumentGenerator argumentGenerator =
17101710
new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes);
17111711

1712-
argumentGenerator.generate(valueArguments, valueArguments);
1712+
argumentGenerator.generate(valueArguments, valueArguments, null);
17131713
}
17141714

17151715
Collection<ClassConstructorDescriptor> constructors = classDescriptor.getConstructors();
@@ -2867,7 +2867,11 @@ public void invokeMethodWithArguments(
28672867
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
28682868

28692869
DefaultCallArgs defaultArgs =
2870-
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()));
2870+
argumentGenerator.generate(
2871+
valueArguments,
2872+
new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()),
2873+
resolvedCall.getResultingDescriptor()
2874+
);
28712875

28722876
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
28732877
tailRecursionCodegen.generateTailRecursion(resolvedCall);

compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
883883
newReceiver.put(newReceiver.type, v);
884884
callGenerator.processAndPutHiddenParameters(false);
885885

886-
defaultArgs = generator.generate(valueArguments, valueArguments);
886+
defaultArgs = generator.generate(valueArguments, valueArguments, call.getResultingDescriptor());
887887
}
888888

889889
private ArgumentGenerator createArgumentGenerator() {

compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,13 +1154,13 @@ else if (container instanceof LazyJavaPackageFragment) {
11541154
}
11551155

11561156
@NotNull
1157-
private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
1157+
private static String getDefaultDescriptor(
1158+
@NotNull Method method,
1159+
@Nullable String dispatchReceiverDescriptor,
1160+
@NotNull CallableDescriptor callableDescriptor
1161+
) {
11581162
String descriptor = method.getDescriptor();
1159-
int argumentsCount = Type.getArgumentTypes(descriptor).length;
1160-
if (isExtension) {
1161-
argumentsCount--;
1162-
}
1163-
int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
1163+
int maskArgumentsCount = (callableDescriptor.getValueParameters().size() + Integer.SIZE - 1) / Integer.SIZE;
11641164
String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
11651165
additionalArgs += (isConstructor(method) ? DEFAULT_CONSTRUCTOR_MARKER : OBJECT_TYPE).getDescriptor();
11661166
String result = descriptor.replace(")", additionalArgs + ")");
@@ -1186,7 +1186,7 @@ public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @
11861186
String descriptor = getDefaultDescriptor(
11871187
jvmSignature,
11881188
isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
1189-
functionDescriptor.getExtensionReceiverParameter() != null
1189+
CodegenUtilKt.unwrapFrontendVersion(functionDescriptor)
11901190
);
11911191

11921192
return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// WITH_RUNTIME
2+
// WITH_COROUTINES
3+
import kotlin.coroutines.experimental.*
4+
import kotlin.coroutines.experimental.intrinsics.*
5+
6+
class Controller {
7+
suspend fun suspendHere(
8+
a: String = "abc",
9+
i1: Int = 1,
10+
i2: Int = 1,
11+
i3: Int = 1,
12+
i4: Int = 1,
13+
i5: Int = 1,
14+
i6: Int = 1,
15+
i7: Int = 1,
16+
i8: Int = 1,
17+
i9: Int = 1,
18+
i10: Int = 1,
19+
i11: Int = 1,
20+
i12: Int = 1,
21+
i13: Int = 1,
22+
i14: Int = 1,
23+
i15: Int = 1,
24+
i16: Int = 1,
25+
i17: Int = 1,
26+
i18: Int = 1,
27+
i19: Int = 1,
28+
i20: Int = 1,
29+
i21: Int = 1,
30+
i22: Int = 1,
31+
i23: Int = 1,
32+
i24: Int = 1,
33+
i25: Int = 1,
34+
i26: Int = 1,
35+
i27: Int = 1,
36+
i28: Int = 1,
37+
i29: Int = 1,
38+
i30: Int = 1,
39+
i31: Int = 1
40+
): String = suspendCoroutineOrReturn { x ->
41+
x.resume(a + "#" + (i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12 + i13 + i14 + i15 + i16 + i17 + i18 + i19 + i20 + i21 + i22 + i23 + i24 + i25 + i26 + i27 + i28 + i29 + i30 + i31))
42+
COROUTINE_SUSPENDED
43+
}
44+
}
45+
46+
fun builder(c: suspend Controller.() -> Unit) {
47+
c.startCoroutine(Controller(), EmptyContinuation)
48+
}
49+
50+
fun box(): String {
51+
var result = "OK"
52+
53+
builder {
54+
var a = suspendHere()
55+
if (a != "abc#31") {
56+
result = "fail 1: $a"
57+
throw RuntimeException(result)
58+
}
59+
60+
a = suspendHere("cde")
61+
if (a != "cde#31") {
62+
result = "fail 2: $a"
63+
throw RuntimeException(result)
64+
}
65+
66+
a = suspendHere(i2 = 6)
67+
if (a != "abc#36") {
68+
result = "fail 3: $a"
69+
throw RuntimeException(result)
70+
}
71+
72+
a = suspendHere("xyz", 9)
73+
if (a != "xyz#39") {
74+
result = "fail 4: $a"
75+
throw RuntimeException(result)
76+
}
77+
}
78+
79+
return result
80+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
enum class ClassTemplate(
2+
// var bug: Int = 1,
3+
var code: Int,
4+
var nameTemplate: Int = 1,
5+
6+
val parent: Int = 1,
7+
val previous: Int = 1,
8+
val progressionEquivalent: Int = 1,
9+
10+
var idDiscipline: Int = 1,
11+
var strictRunningOrder: Int = 1,
12+
var pointsMethod: Int = 1,
13+
14+
var noTimeFaults: Int = 1,
15+
var combineHeights: Int = 1,
16+
17+
var column: Int = 1,
18+
var runningOrderSort: Int = 1,
19+
var programme: Int = 1,
20+
var eliminationTime: Int = 1,
21+
var courseTimeCode: Int = 1,
22+
var teamSize: Int = 1,
23+
var sponsor: Int = 1,
24+
var lateEntryCredits: Int = 1,
25+
var lateEntryFee: Int = 1,
26+
27+
var courseLengthNeeded: Int = 1,
28+
29+
var discretionaryCourseTime: Int = 1,
30+
var isRelay: Int = 1,
31+
var isQualifier: Int = 1,
32+
var generateChildren: Int = 1,
33+
var feedFromParent: Int = 1,
34+
35+
var isNfcAllowed: Int = 1,
36+
var isAddOnAllowed: Int = 1,
37+
var isSpecialEntry: Int = 1,
38+
var isUkaProgression: Int = 1,
39+
var canEnterDirectly: Int = 1,
40+
var isPointRanked: Int = 1,
41+
var isPointRankedDesc: Int = 1
42+
) {
43+
UNDEFINED(code = 56, nameTemplate = 3),
44+
BLAH(code = 57, nameTemplate = 4)
45+
}
46+
47+
fun box(): String {
48+
val x = ClassTemplate.UNDEFINED
49+
val y = ClassTemplate.BLAH
50+
51+
if (x.code != 56 || x.nameTemplate != 3 || x.isAddOnAllowed != 1) return "fail 1"
52+
if (y.code != 57 || y.nameTemplate != 4 || y.isAddOnAllowed != 1) return "fail 2"
53+
54+
return "OK"
55+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@kotlin.Metadata
2+
public final class Controller {
3+
public method <init>(): void
4+
public synthetic static method suspendHere$default(p0: Controller, p1: java.lang.String, p2: int, p3: int, p4: int, p5: int, p6: int, p7: int, p8: int, p9: int, p10: int, p11: int, p12: int, p13: int, p14: int, p15: int, p16: int, p17: int, p18: int, p19: int, p20: int, p21: int, p22: int, p23: int, p24: int, p25: int, p26: int, p27: int, p28: int, p29: int, p30: int, p31: int, p32: int, p33: kotlin.coroutines.experimental.Continuation, p34: int, p35: java.lang.Object): java.lang.Object
5+
public final @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: java.lang.String, p1: int, p2: int, p3: int, p4: int, p5: int, p6: int, p7: int, p8: int, p9: int, p10: int, p11: int, p12: int, p13: int, p14: int, p15: int, p16: int, p17: int, p18: int, p19: int, p20: int, p21: int, p22: int, p23: int, p24: int, p25: int, p26: int, p27: int, p28: int, p29: int, p30: int, p31: int, @org.jetbrains.annotations.NotNull p32: kotlin.coroutines.experimental.Continuation): java.lang.Object
6+
}
7+
8+
@kotlin.Metadata
9+
public final class CoroutineUtilKt {
10+
public final static @org.jetbrains.annotations.NotNull method handleExceptionContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation
11+
public final static @org.jetbrains.annotations.NotNull method handleResultContinuation(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): kotlin.coroutines.experimental.Continuation
12+
}
13+
14+
@kotlin.Metadata
15+
public class EmptyContinuation {
16+
public final static field Companion: EmptyContinuation.Companion
17+
private final @org.jetbrains.annotations.NotNull field context: kotlin.coroutines.experimental.CoroutineContext
18+
inner class EmptyContinuation/Companion
19+
public @synthetic.kotlin.jvm.GeneratedByJvmOverloads method <init>(): void
20+
public method <init>(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.CoroutineContext): void
21+
public synthetic method <init>(p0: kotlin.coroutines.experimental.CoroutineContext, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void
22+
public @org.jetbrains.annotations.NotNull method getContext(): kotlin.coroutines.experimental.CoroutineContext
23+
public method resume(@org.jetbrains.annotations.Nullable p0: java.lang.Object): void
24+
public method resumeWithException(@org.jetbrains.annotations.NotNull p0: java.lang.Throwable): void
25+
}
26+
27+
@kotlin.Metadata
28+
public final static class EmptyContinuation/Companion {
29+
inner class EmptyContinuation/Companion
30+
private method <init>(): void
31+
}
32+
33+
@kotlin.Metadata
34+
public final class _32defaultParametersInSuspendKt {
35+
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
36+
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void
37+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
@kotlin.Metadata
2+
public enum class ClassTemplate {
3+
public final static field BLAH: ClassTemplate
4+
public final static field UNDEFINED: ClassTemplate
5+
private field canEnterDirectly: int
6+
private field code: int
7+
private field column: int
8+
private field combineHeights: int
9+
private field courseLengthNeeded: int
10+
private field courseTimeCode: int
11+
private field discretionaryCourseTime: int
12+
private field eliminationTime: int
13+
private field feedFromParent: int
14+
private field generateChildren: int
15+
private field idDiscipline: int
16+
private field isAddOnAllowed: int
17+
private field isNfcAllowed: int
18+
private field isPointRanked: int
19+
private field isPointRankedDesc: int
20+
private field isQualifier: int
21+
private field isRelay: int
22+
private field isSpecialEntry: int
23+
private field isUkaProgression: int
24+
private field lateEntryCredits: int
25+
private field lateEntryFee: int
26+
private field nameTemplate: int
27+
private field noTimeFaults: int
28+
private final field parent: int
29+
private field pointsMethod: int
30+
private final field previous: int
31+
private field programme: int
32+
private final field progressionEquivalent: int
33+
private field runningOrderSort: int
34+
private field sponsor: int
35+
private field strictRunningOrder: int
36+
private field teamSize: int
37+
protected method <init>(p0: java.lang.String, p1: int, p2: int, p3: int, p4: int, p5: int, p6: int, p7: int, p8: int, p9: int, p10: int, p11: int, p12: int, p13: int, p14: int, p15: int, p16: int, p17: int, p18: int, p19: int, p20: int, p21: int, p22: int, p23: int, p24: int, p25: int, p26: int, p27: int, p28: int, p29: int, p30: int, p31: int, p32: int, p33: int): void
38+
synthetic method <init>(p0: java.lang.String, p1: int, p2: int, p3: int, p4: int, p5: int, p6: int, p7: int, p8: int, p9: int, p10: int, p11: int, p12: int, p13: int, p14: int, p15: int, p16: int, p17: int, p18: int, p19: int, p20: int, p21: int, p22: int, p23: int, p24: int, p25: int, p26: int, p27: int, p28: int, p29: int, p30: int, p31: int, p32: int, p33: int, p34: int, p35: kotlin.jvm.internal.DefaultConstructorMarker): void
39+
public final method getCanEnterDirectly(): int
40+
public final method getCode(): int
41+
public final method getColumn(): int
42+
public final method getCombineHeights(): int
43+
public final method getCourseLengthNeeded(): int
44+
public final method getCourseTimeCode(): int
45+
public final method getDiscretionaryCourseTime(): int
46+
public final method getEliminationTime(): int
47+
public final method getFeedFromParent(): int
48+
public final method getGenerateChildren(): int
49+
public final method getIdDiscipline(): int
50+
public final method getLateEntryCredits(): int
51+
public final method getLateEntryFee(): int
52+
public final method getNameTemplate(): int
53+
public final method getNoTimeFaults(): int
54+
public final method getParent(): int
55+
public final method getPointsMethod(): int
56+
public final method getPrevious(): int
57+
public final method getProgramme(): int
58+
public final method getProgressionEquivalent(): int
59+
public final method getRunningOrderSort(): int
60+
public final method getSponsor(): int
61+
public final method getStrictRunningOrder(): int
62+
public final method getTeamSize(): int
63+
public final method isAddOnAllowed(): int
64+
public final method isNfcAllowed(): int
65+
public final method isPointRanked(): int
66+
public final method isPointRankedDesc(): int
67+
public final method isQualifier(): int
68+
public final method isRelay(): int
69+
public final method isSpecialEntry(): int
70+
public final method isUkaProgression(): int
71+
public final method setAddOnAllowed(p0: int): void
72+
public final method setCanEnterDirectly(p0: int): void
73+
public final method setCode(p0: int): void
74+
public final method setColumn(p0: int): void
75+
public final method setCombineHeights(p0: int): void
76+
public final method setCourseLengthNeeded(p0: int): void
77+
public final method setCourseTimeCode(p0: int): void
78+
public final method setDiscretionaryCourseTime(p0: int): void
79+
public final method setEliminationTime(p0: int): void
80+
public final method setFeedFromParent(p0: int): void
81+
public final method setGenerateChildren(p0: int): void
82+
public final method setIdDiscipline(p0: int): void
83+
public final method setLateEntryCredits(p0: int): void
84+
public final method setLateEntryFee(p0: int): void
85+
public final method setNameTemplate(p0: int): void
86+
public final method setNfcAllowed(p0: int): void
87+
public final method setNoTimeFaults(p0: int): void
88+
public final method setPointRanked(p0: int): void
89+
public final method setPointRankedDesc(p0: int): void
90+
public final method setPointsMethod(p0: int): void
91+
public final method setProgramme(p0: int): void
92+
public final method setQualifier(p0: int): void
93+
public final method setRelay(p0: int): void
94+
public final method setRunningOrderSort(p0: int): void
95+
public final method setSpecialEntry(p0: int): void
96+
public final method setSponsor(p0: int): void
97+
public final method setStrictRunningOrder(p0: int): void
98+
public final method setTeamSize(p0: int): void
99+
public final method setUkaProgression(p0: int): void
100+
public static method valueOf(p0: java.lang.String): ClassTemplate
101+
public static method values(): ClassTemplate[]
102+
}
103+
104+
@kotlin.Metadata
105+
public final class ManyDefaultParametersKt {
106+
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
107+
}

0 commit comments

Comments
 (0)