Support default arguments for expected declarations

#KT-21913 Fixed
This commit is contained in:
Alexander Udalov
2018-01-12 20:50:24 +01:00
parent d356f52873
commit db4ce703a6
36 changed files with 794 additions and 77 deletions
@@ -12,6 +12,7 @@ import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CodegenUtil;
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
@@ -73,6 +74,7 @@ import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DEC
import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND;
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
@@ -585,8 +587,10 @@ public class FunctionCodegen {
methodEnd = new Label();
}
else {
FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(),
functionDescriptor));
FrameMap frameMap = createFrameMap(
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
functionDescriptor.getValueParameters(), isStaticMethod(context.getContextKind(), functionDescriptor)
);
if (context.isInlineMethodContext()) {
functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
}
@@ -1046,7 +1050,7 @@ public class FunctionCodegen {
return;
}
if (!isDefaultNeeded(functionDescriptor)) {
if (!isDefaultNeeded(functionDescriptor, function)) {
return;
}
@@ -1106,8 +1110,19 @@ public class FunctionCodegen {
GenerationState state = parentCodegen.state;
JvmMethodSignature signature = state.getTypeMapper().mapSignatureWithGeneric(functionDescriptor, methodContext.getContextKind());
List<ValueParameterDescriptor> originalParameters = functionDescriptor.getValueParameters();
List<ValueParameterDescriptor> valueParameters;
if (functionDescriptor.isActual() && CollectionsKt.none(originalParameters, ValueParameterDescriptor::declaresDefaultValue)) {
FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(functionDescriptor);
assert expected != null : "Expected function should have been found earlier for " + functionDescriptor;
valueParameters = expected.getValueParameters();
}
else {
valueParameters = originalParameters;
}
boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic);
FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
@@ -1123,7 +1138,6 @@ public class FunctionCodegen {
capturedArgumentsCount++;
}
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
assert valueParameters.size() > 0 : "Expecting value parameters to generate default function " + functionDescriptor;
int firstMaskIndex = frameMap.enterTemp(Type.INT_TYPE);
for (int index = 1; index < valueParameters.size(); index++) {
@@ -1191,10 +1205,11 @@ public class FunctionCodegen {
}
@NotNull
public static FrameMap createFrameMap(
private static FrameMap createFrameMap(
@NotNull GenerationState state,
@NotNull FunctionDescriptor function,
@NotNull JvmMethodSignature signature,
@Nullable ReceiverParameterDescriptor extensionReceiverParameter,
@NotNull List<ValueParameterDescriptor> valueParameters,
boolean isStatic
) {
FrameMap frameMap = new FrameMap();
@@ -1204,9 +1219,8 @@ public class FunctionCodegen {
for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) {
ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
if (receiverParameter != null) {
frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter));
if (extensionReceiverParameter != null) {
frameMap.enter(extensionReceiverParameter, state.getTypeMapper().mapType(extensionReceiverParameter));
}
else {
frameMap.enterTemp(parameter.getAsmType());
@@ -1217,7 +1231,7 @@ public class FunctionCodegen {
}
}
for (ValueParameterDescriptor parameter : function.getValueParameters()) {
for (ValueParameterDescriptor parameter : valueParameters) {
frameMap.enter(parameter, state.getTypeMapper().mapType(parameter));
}
@@ -1245,17 +1259,23 @@ public class FunctionCodegen {
}
}
private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) {
boolean needed = false;
if (functionDescriptor != null) {
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
if (parameterDescriptor.declaresDefaultValue()) {
needed = true;
break;
private boolean isDefaultNeeded(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
if (descriptor.isActual()) {
FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor);
if (expected != null && CollectionsKt.any(expected.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue)) {
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(expected);
if (element == null) {
if (function != null) {
state.getDiagnostics().report(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(function));
}
return false;
}
return true;
}
}
return needed;
return CollectionsKt.any(descriptor.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue);
}
private void generateBridge(
@@ -280,8 +280,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
val parentContext = context.parentContext ?: error("Context has no parent: " + context)
val methodContext = parentContext.intoFunction(callableDescriptor)
val smap: SMAP
if (callDefault) {
val smap = if (callDefault) {
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
val parentCodegen = FakeMemberCodegen(
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
@@ -293,13 +292,13 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
}
FunctionCodegen.generateDefaultImplBody(
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction as KtNamedFunction?, parentCodegen, asmMethod
)
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
createSMAPWithDefaultMapping(inliningFunction, parentCodegen.orCreateSourceMapper.resultMappings)
}
else {
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction!!, jvmSignature, null)
}
maxCalcAdapter.visitMaxs(-1, -1)
maxCalcAdapter.visitEnd()