Fix for KT-9140: Default parameters are passed as nulls when using indexing [ ] invocation
#KT-9140 Fixed
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
class DefaultCallMask(val size: Int) {
|
||||
@@ -48,4 +49,12 @@ class DefaultCallMask(val size: Int) {
|
||||
|
||||
return masks
|
||||
}
|
||||
|
||||
public fun generateOnStackIfNeeded(callGenerator: CallGenerator): Boolean {
|
||||
val toInts = toInts()
|
||||
for (mask in toInts) {
|
||||
callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE))
|
||||
}
|
||||
return toInts.isNotEmpty();
|
||||
}
|
||||
}
|
||||
@@ -2477,18 +2477,15 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex();
|
||||
assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor();
|
||||
|
||||
List<Integer> masks =
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()))
|
||||
.toInts();
|
||||
DefaultCallMask masks =
|
||||
argumentGenerator.generate(valueArguments, new ArrayList<ResolvedValueArgument>(resolvedCall.getValueArguments().values()));
|
||||
|
||||
if (tailRecursionCodegen.isTailRecursion(resolvedCall)) {
|
||||
tailRecursionCodegen.generateTailRecursion(resolvedCall);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int mask : masks) {
|
||||
callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE));
|
||||
}
|
||||
boolean defaultMaskWasGenerated = masks.generateOnStackIfNeeded(callGenerator);
|
||||
|
||||
// Extra constructor marker argument
|
||||
if (callableMethod instanceof CallableMethod) {
|
||||
@@ -2500,7 +2497,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
callGenerator.genCall(callableMethod, resolvedCall, !masks.isEmpty(), this);
|
||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -3532,7 +3529,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Callable callableMethod = resolveToCallableMethod(operationDescriptor, false);
|
||||
Type[] argumentTypes = callableMethod.getParameterTypes();
|
||||
|
||||
StackValue collectionElementReceiver = createCollectionElementReceiver(
|
||||
StackValue.CollectionElementReceiver collectionElementReceiver = createCollectionElementReceiver(
|
||||
expression, receiver, operationDescriptor, isGetter, resolvedGetCall, resolvedSetCall, callable
|
||||
);
|
||||
|
||||
@@ -3542,7 +3539,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue createCollectionElementReceiver(
|
||||
private StackValue.CollectionElementReceiver createCollectionElementReceiver(
|
||||
@NotNull KtArrayAccessExpression expression,
|
||||
@NotNull StackValue receiver,
|
||||
@NotNull FunctionDescriptor operationDescriptor,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import kotlin.ArraysKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
@@ -201,7 +203,7 @@ public abstract class StackValue {
|
||||
|
||||
@NotNull
|
||||
public static StackValue collectionElement(
|
||||
StackValue collectionElementReceiver,
|
||||
CollectionElementReceiver collectionElementReceiver,
|
||||
Type type,
|
||||
ResolvedCall<FunctionDescriptor> getter,
|
||||
ResolvedCall<FunctionDescriptor> setter,
|
||||
@@ -769,11 +771,12 @@ public abstract class StackValue {
|
||||
private final boolean isGetter;
|
||||
private final ExpressionCodegen codegen;
|
||||
private final ArgumentGenerator argumentGenerator;
|
||||
private final List<ResolvedValueArgument> valueArguments;
|
||||
final List<ResolvedValueArgument> valueArguments;
|
||||
private final FrameMap frame;
|
||||
private final StackValue receiver;
|
||||
private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
|
||||
private final ResolvedCall<FunctionDescriptor> resolvedSetCall;
|
||||
DefaultCallMask mask;
|
||||
|
||||
public CollectionElementReceiver(
|
||||
@NotNull Callable callable,
|
||||
@@ -803,7 +806,7 @@ public abstract class StackValue {
|
||||
ResolvedCall<?> call = isGetter ? resolvedGetCall : resolvedSetCall;
|
||||
StackValue newReceiver = StackValue.receiver(call, receiver, codegen, callable);
|
||||
newReceiver.put(newReceiver.type, v);
|
||||
argumentGenerator.generate(valueArguments, valueArguments);
|
||||
mask = argumentGenerator.generate(valueArguments, valueArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -912,7 +915,7 @@ public abstract class StackValue {
|
||||
private final FunctionDescriptor getterDescriptor;
|
||||
|
||||
public CollectionElement(
|
||||
@NotNull StackValue collectionElementReceiver,
|
||||
@NotNull CollectionElementReceiver collectionElementReceiver,
|
||||
@NotNull Type type,
|
||||
@Nullable ResolvedCall<FunctionDescriptor> resolvedGetCall,
|
||||
@Nullable ResolvedCall<FunctionDescriptor> resolvedSetCall,
|
||||
@@ -933,11 +936,16 @@ public abstract class StackValue {
|
||||
if (getter == null) {
|
||||
throw new UnsupportedOperationException("no getter specified");
|
||||
}
|
||||
|
||||
getter.genInvokeInstruction(v);
|
||||
CallGenerator callGenerator = codegen.defaultCallGenerator;
|
||||
callGenerator.genCall(getter, resolvedGetCall, genDefaultMaskIfPresent(callGenerator), codegen);
|
||||
coerceTo(type, v);
|
||||
}
|
||||
|
||||
private boolean genDefaultMaskIfPresent(CallGenerator callGenerator) {
|
||||
DefaultCallMask mask = ((CollectionElementReceiver) receiver).mask;
|
||||
return mask.generateOnStackIfNeeded(callGenerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiverSize() {
|
||||
if (isStandardStack(codegen.typeMapper, resolvedGetCall, 1) && isStandardStack(codegen.typeMapper, resolvedSetCall, 2)) {
|
||||
@@ -985,9 +993,25 @@ public abstract class StackValue {
|
||||
throw new UnsupportedOperationException("no setter specified");
|
||||
}
|
||||
|
||||
Type[] argumentTypes = setter.getParameterTypes();
|
||||
coerce(topOfStackType, argumentTypes[argumentTypes.length - 1], v);
|
||||
setter.genInvokeInstruction(v);
|
||||
Type lastParameterType = ArraysKt.last(setter.getParameterTypes());
|
||||
coerce(topOfStackType, lastParameterType, v);
|
||||
//*Convention setter couldn't have default parameters, just getter can have it at last positions
|
||||
//We should remove default parameters of getter from stack*/
|
||||
CollectionElementReceiver collectionElementReceiver = (CollectionElementReceiver) receiver;
|
||||
if (collectionElementReceiver.isGetter) {
|
||||
List<ResolvedValueArgument> arguments = collectionElementReceiver.valueArguments;
|
||||
List<Type> types = getter.getValueParameterTypes();
|
||||
for (int i = arguments.size() - 1; i >= 0; i--) {
|
||||
ResolvedValueArgument argument = arguments.get(i);
|
||||
if (argument instanceof DefaultValueArgument) {
|
||||
Type defaultType = types.get(i);
|
||||
AsmUtil.swap(v, lastParameterType, defaultType);
|
||||
AsmUtil.pop(v, defaultType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codegen.defaultCallGenerator.genCall(setter, resolvedSetCall, false, codegen);
|
||||
Type returnType = setter.getReturnType();
|
||||
if (returnType != Type.VOID_TYPE) {
|
||||
pop(v, returnType);
|
||||
|
||||
Reference in New Issue
Block a user