001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.codegen;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.util.ArrayUtil;
021    import kotlin.Pair;
022    import kotlin.Unit;
023    import kotlin.collections.CollectionsKt;
024    import kotlin.jvm.functions.Function1;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
028    import org.jetbrains.kotlin.codegen.context.ClosureContext;
029    import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
030    import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
031    import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
032    import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
033    import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
034    import org.jetbrains.kotlin.codegen.state.GenerationState;
035    import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
036    import org.jetbrains.kotlin.descriptors.*;
037    import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
038    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
039    import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
040    import org.jetbrains.kotlin.load.java.JvmAbi;
041    import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
042    import org.jetbrains.kotlin.psi.KtElement;
043    import org.jetbrains.kotlin.resolve.BindingContext;
044    import org.jetbrains.kotlin.resolve.DescriptorUtils;
045    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
046    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
047    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
048    import org.jetbrains.kotlin.serialization.DescriptorSerializer;
049    import org.jetbrains.kotlin.serialization.ProtoBuf;
050    import org.jetbrains.kotlin.types.KotlinType;
051    import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
052    import org.jetbrains.kotlin.util.OperatorNameConventions;
053    import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
054    import org.jetbrains.org.objectweb.asm.MethodVisitor;
055    import org.jetbrains.org.objectweb.asm.Type;
056    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
057    import org.jetbrains.org.objectweb.asm.commons.Method;
058    
059    import java.util.ArrayList;
060    import java.util.Collections;
061    import java.util.List;
062    
063    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
064    import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
065    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
066    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
067    import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
068    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
069    import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
070    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
071    
072    public class ClosureCodegen extends MemberCodegen<KtElement> {
073        protected final FunctionDescriptor funDescriptor;
074        private final ClassDescriptor classDescriptor;
075        private final SamType samType;
076        private final KotlinType superClassType;
077        private final List<KotlinType> superInterfaceTypes;
078        private final FunctionDescriptor functionReferenceTarget;
079        private final FunctionGenerationStrategy strategy;
080        protected final CalculatedClosure closure;
081        protected final Type asmType;
082        protected final int visibilityFlag;
083        private final boolean shouldHaveBoundReferenceReceiver;
084    
085        private Method constructor;
086        protected Type superClassAsmType;
087    
088        public ClosureCodegen(
089                @NotNull GenerationState state,
090                @NotNull KtElement element,
091                @Nullable SamType samType,
092                @NotNull ClosureContext context,
093                @Nullable FunctionDescriptor functionReferenceTarget,
094                @NotNull FunctionGenerationStrategy strategy,
095                @NotNull MemberCodegen<?> parentCodegen,
096                @NotNull ClassBuilder classBuilder
097        ) {
098            super(state, parentCodegen, context, element, classBuilder);
099    
100            this.funDescriptor = context.getFunctionDescriptor();
101            this.classDescriptor = context.getContextDescriptor();
102            this.samType = samType;
103            this.functionReferenceTarget = functionReferenceTarget;
104            this.strategy = strategy;
105    
106            if (samType == null) {
107                this.superInterfaceTypes = new ArrayList<KotlinType>();
108    
109                KotlinType superClassType = null;
110                for (KotlinType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
111                    ClassifierDescriptor classifier = supertype.getConstructor().getDeclarationDescriptor();
112                    if (DescriptorUtils.isInterface(classifier)) {
113                        superInterfaceTypes.add(supertype);
114                    }
115                    else {
116                        assert superClassType == null : "Closure class can't have more than one superclass: " + funDescriptor;
117                        superClassType = supertype;
118                    }
119                }
120                assert superClassType != null : "Closure class should have a superclass: " + funDescriptor;
121    
122                this.superClassType = superClassType;
123            }
124            else {
125                this.superInterfaceTypes = Collections.singletonList(samType.getType());
126                this.superClassType = DescriptorUtilsKt.getBuiltIns(funDescriptor).getAnyType();
127            }
128    
129            this.closure = bindingContext.get(CLOSURE, classDescriptor);
130            assert closure != null : "Closure must be calculated for class: " + classDescriptor;
131    
132            this.shouldHaveBoundReferenceReceiver = CallableReferenceUtilKt.isForBoundCallableReference(closure);
133    
134            this.asmType = typeMapper.mapClass(classDescriptor);
135    
136            visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor);
137        }
138    
139        @Override
140        protected void generateDeclaration() {
141            JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
142            if (samType != null) {
143                typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw);
144            }
145            sw.writeSuperclass();
146            superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
147            sw.writeSuperclassEnd();
148            String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()];
149            for (int i = 0; i < superInterfaceTypes.size(); i++) {
150                KotlinType superInterfaceType = superInterfaceTypes.get(i);
151                sw.writeInterface();
152                superInterfaceAsmTypes[i] = typeMapper.mapSupertype(superInterfaceType, sw).getInternalName();
153                sw.writeInterfaceEnd();
154            }
155    
156            v.defineClass(element,
157                          state.getClassFileVersion(),
158                          ACC_FINAL | ACC_SUPER | visibilityFlag,
159                          asmType.getInternalName(),
160                          sw.makeJavaGenericSignature(),
161                          superClassAsmType.getInternalName(),
162                          superInterfaceAsmTypes
163            );
164    
165            InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
166    
167            v.visitSource(element.getContainingFile().getName(), null);
168        }
169    
170        @Nullable
171        @Override
172        protected ClassDescriptor classForInnerClassRecord() {
173            return JvmCodegenUtil.isArgumentWhichWillBeInlined(bindingContext, funDescriptor) ? null : classDescriptor;
174        }
175    
176        @Override
177        protected void generateBody() {
178            generateBridges();
179            generateClosureBody();
180    
181            this.constructor = generateConstructor();
182    
183            if (isConst(closure)) {
184                generateConstInstance(asmType, asmType);
185            }
186    
187            genClosureFields(closure, v, typeMapper);
188        }
189    
190        protected void generateClosureBody() {
191            functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), funDescriptor, strategy);
192    
193            if (functionReferenceTarget != null) {
194                generateFunctionReferenceMethods(functionReferenceTarget);
195            }
196    
197            functionCodegen.generateDefaultIfNeeded(
198                    context.intoFunction(funDescriptor), funDescriptor, context.getContextKind(), DefaultParameterValueLoader.DEFAULT, null
199            );
200        }
201    
202        protected void generateBridges() {
203            FunctionDescriptor erasedInterfaceFunction;
204            if (samType == null) {
205                erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
206            }
207            else {
208                erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
209            }
210    
211            generateBridge(
212                    typeMapper.mapAsmMethod(erasedInterfaceFunction),
213                    typeMapper.mapAsmMethod(funDescriptor)
214            );
215    
216            //TODO: rewrite cause ugly hack
217            if (samType != null) {
218                SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl
219                        .create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(),
220                                erasedInterfaceFunction.getName(),
221                                CallableMemberDescriptor.Kind.DECLARATION, funDescriptor.getSource());
222    
223                descriptorForBridges
224                        .initialize(null, erasedInterfaceFunction.getDispatchReceiverParameter(), erasedInterfaceFunction.getTypeParameters(),
225                                    erasedInterfaceFunction.getValueParameters(), erasedInterfaceFunction.getReturnType(),
226                                    Modality.OPEN, erasedInterfaceFunction.getVisibility());
227    
228                DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, erasedInterfaceFunction);
229                functionCodegen.generateBridges(descriptorForBridges);
230            }
231        }
232    
233        @Override
234        protected void generateKotlinMetadataAnnotation() {
235            FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
236            FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
237            Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
238            assert method != null : "No method for " + frontendFunDescriptor;
239            v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
240    
241            final DescriptorSerializer serializer =
242                    DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
243    
244            final ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
245    
246            WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, new Function1<AnnotationVisitor, Unit>() {
247                @Override
248                public Unit invoke(AnnotationVisitor av) {
249                    writeAnnotationData(av, serializer, functionProto);
250                    return Unit.INSTANCE;
251                }
252            });
253        }
254    
255        /**
256         * Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
257         * This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
258         */
259        @NotNull
260        private static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
261            FunctionDescriptor.CopyBuilder<? extends FunctionDescriptor> builder = descriptor.newCopyBuilder();
262            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
263            builder.setTypeParameters(typeParameters);
264    
265            DeclarationDescriptor container = descriptor.getContainingDeclaration();
266            while (container != null) {
267                if (container instanceof ClassDescriptor) {
268                    typeParameters.addAll(((ClassDescriptor) container).getDeclaredTypeParameters());
269                }
270                else if (container instanceof CallableDescriptor && !(container instanceof ConstructorDescriptor)) {
271                    typeParameters.addAll(((CallableDescriptor) container).getTypeParameters());
272                }
273                container = container.getContainingDeclaration();
274            }
275    
276            return typeParameters.isEmpty() ? descriptor : builder.build();
277        }
278    
279        @Override
280        protected void done() {
281            writeOuterClassAndEnclosingMethod();
282            super.done();
283        }
284    
285        @NotNull
286        public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen, @Nullable final StackValue functionReferenceReceiver) {
287            return StackValue.operation(
288                    functionReferenceTarget != null ? K_FUNCTION : asmType,
289                    new Function1<InstructionAdapter, Unit>() {
290                        @Override
291                        public Unit invoke(InstructionAdapter v) {
292                            if (isConst(closure)) {
293                                v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
294                            }
295                            else {
296                                v.anew(asmType);
297                                v.dup();
298    
299                                codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator, functionReferenceReceiver);
300                                v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
301                            }
302    
303                            return Unit.INSTANCE;
304                        }
305                    }
306            );
307        }
308    
309        protected void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
310            if (bridge.equals(delegate)) return;
311    
312            MethodVisitor mv =
313                    v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC,
314                                bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
315    
316            if (!state.getClassBuilderMode().generateBodies) return;
317    
318            mv.visitCode();
319    
320            InstructionAdapter iv = new InstructionAdapter(mv);
321            MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
322    
323            iv.load(0, asmType);
324    
325            Type[] myParameterTypes = bridge.getArgumentTypes();
326    
327            List<ParameterDescriptor> calleeParameters = CollectionsKt.plus(
328                    org.jetbrains.kotlin.utils.CollectionsKt.<ParameterDescriptor>singletonOrEmptyList(funDescriptor.getExtensionReceiverParameter()),
329                    funDescriptor.getValueParameters()
330            );
331    
332            int slot = 1;
333            for (int i = 0; i < calleeParameters.size(); i++) {
334                Type type = myParameterTypes[i];
335                StackValue.local(slot, type).put(typeMapper.mapType(calleeParameters.get(i)), iv);
336                slot += type.getSize();
337            }
338    
339            iv.invokevirtual(asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false);
340            StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), iv);
341    
342            iv.areturn(bridge.getReturnType());
343    
344            FunctionCodegen.endVisit(mv, "bridge", element);
345        }
346    
347        // TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
348        private void generateFunctionReferenceMethods(@NotNull FunctionDescriptor descriptor) {
349            int flags = ACC_PUBLIC | ACC_FINAL;
350            boolean generateBody = state.getClassBuilderMode().generateBodies;
351    
352            {
353                MethodVisitor mv =
354                        v.newMethod(NO_ORIGIN, flags, "getOwner", Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE), null, null);
355                if (generateBody) {
356                    mv.visitCode();
357                    InstructionAdapter iv = new InstructionAdapter(mv);
358                    generateCallableReferenceDeclarationContainer(iv, descriptor, state);
359                    iv.areturn(K_DECLARATION_CONTAINER_TYPE);
360                    FunctionCodegen.endVisit(iv, "function reference getOwner", element);
361                }
362            }
363    
364            {
365                MethodVisitor mv =
366                        v.newMethod(NO_ORIGIN, flags, "getName", Type.getMethodDescriptor(JAVA_STRING_TYPE), null, null);
367                if (generateBody) {
368                    mv.visitCode();
369                    InstructionAdapter iv = new InstructionAdapter(mv);
370                    iv.aconst(descriptor.getName().asString());
371                    iv.areturn(JAVA_STRING_TYPE);
372                    FunctionCodegen.endVisit(iv, "function reference getName", element);
373                }
374            }
375    
376            {
377                MethodVisitor mv = v.newMethod(NO_ORIGIN, flags, "getSignature", Type.getMethodDescriptor(JAVA_STRING_TYPE), null, null);
378                if (generateBody) {
379                    mv.visitCode();
380                    InstructionAdapter iv = new InstructionAdapter(mv);
381                    PropertyReferenceCodegen.generateCallableReferenceSignature(iv, descriptor, state);
382                    iv.areturn(JAVA_STRING_TYPE);
383                    FunctionCodegen.endVisit(iv, "function reference getSignature", element);
384                }
385            }
386        }
387    
388        public static void generateCallableReferenceDeclarationContainer(
389                @NotNull InstructionAdapter iv,
390                @NotNull CallableDescriptor descriptor,
391                @NotNull GenerationState state
392        ) {
393            DeclarationDescriptor container = descriptor.getContainingDeclaration();
394            if (container instanceof ClassDescriptor) {
395                // TODO: getDefaultType() here is wrong and won't work for arrays
396                putJavaLangClassInstance(iv, state.getTypeMapper().mapType(((ClassDescriptor) container).getDefaultType()));
397                wrapJavaClassIntoKClass(iv);
398            }
399            else if (container instanceof PackageFragmentDescriptor) {
400                iv.aconst(state.getTypeMapper().mapOwner(descriptor));
401                iv.aconst(state.getModuleName());
402                iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
403                                Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
404            }
405            else {
406                iv.aconst(null);
407            }
408        }
409    
410        @NotNull
411        protected Method generateConstructor() {
412            List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
413    
414            Type[] argTypes = fieldListToTypeArray(args);
415    
416            Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
417            MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null,
418                                           ArrayUtil.EMPTY_STRING_ARRAY);
419            if (state.getClassBuilderMode().generateBodies) {
420                mv.visitCode();
421                InstructionAdapter iv = new InstructionAdapter(mv);
422    
423                Pair<Integer, Type> receiverIndexAndType =
424                        CallableReferenceUtilKt.generateClosureFieldsInitializationFromParameters(iv, closure, args);
425                if (shouldHaveBoundReferenceReceiver && receiverIndexAndType == null) {
426                    throw new AssertionError("No bound reference receiver in constructor parameters: " + args);
427                }
428                int boundReferenceReceiverParameterIndex = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getFirst() : -1;
429                Type boundReferenceReceiverType = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getSecond() : null;
430    
431                iv.load(0, superClassAsmType);
432    
433                String superClassConstructorDescriptor;
434                if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
435                    superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) {
436                    int arity = calculateArity();
437                    iv.iconst(arity);
438                    if (shouldHaveBoundReferenceReceiver) {
439                        CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReferenceReceiverParameterIndex, boundReferenceReceiverType);
440                        superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
441                    }
442                    else {
443                        superClassConstructorDescriptor = "(I)V";
444                    }
445                }
446                else {
447                    assert !shouldHaveBoundReferenceReceiver : "Unexpected bound reference with supertype " + superClassAsmType;
448                    superClassConstructorDescriptor = "()V";
449                }
450                iv.invokespecial(superClassAsmType.getInternalName(), "<init>", superClassConstructorDescriptor, false);
451    
452                iv.visitInsn(RETURN);
453    
454                FunctionCodegen.endVisit(iv, "constructor", element);
455            }
456            return constructor;
457        }
458    
459        protected int calculateArity() {
460            int arity = funDescriptor.getValueParameters().size();
461            if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
462            if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
463            return arity;
464        }
465    
466        @NotNull
467        public static List<FieldInfo> calculateConstructorParameters(
468                @NotNull KotlinTypeMapper typeMapper,
469                @NotNull CalculatedClosure closure,
470                @NotNull Type ownerType
471        ) {
472            BindingContext bindingContext = typeMapper.getBindingContext();
473            List<FieldInfo> args = Lists.newArrayList();
474            ClassDescriptor captureThis = closure.getCaptureThis();
475            if (captureThis != null) {
476                Type type = typeMapper.mapType(captureThis);
477                args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD));
478            }
479            KotlinType captureReceiverType = closure.getCaptureReceiverType();
480            if (captureReceiverType != null) {
481                args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD));
482            }
483    
484            for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
485                if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
486                    Type type = typeMapper.getSharedVarType(descriptor);
487                    if (type == null && descriptor instanceof LocalVariableDescriptor) {
488                        KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType((LocalVariableDescriptor) descriptor, bindingContext);
489                        if (delegateType != null) {
490                            type = typeMapper.mapType(delegateType);
491                        }
492                    }
493                    if (type == null) {
494                        type = typeMapper.mapType((VariableDescriptor) descriptor);
495                    }
496                    args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
497                }
498                else if (ExpressionTypingUtils.isLocalFunction(descriptor)) {
499                    Type classType = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
500                    args.add(FieldInfo.createForHiddenField(ownerType, classType, "$" + descriptor.getName().asString()));
501                }
502                else if (descriptor instanceof FunctionDescriptor) {
503                    assert captureReceiverType != null;
504                }
505            }
506            return args;
507        }
508    
509        private static Type[] fieldListToTypeArray(List<FieldInfo> args) {
510            Type[] argTypes = new Type[args.size()];
511            for (int i = 0; i != argTypes.length; ++i) {
512                argTypes[i] = args.get(i).getFieldType();
513            }
514            return argTypes;
515        }
516    
517        @NotNull
518        public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor function) {
519            ClassDescriptor functionClass = DescriptorUtilsKt.getBuiltIns(function).getFunction(
520                    function.getValueParameters().size() + (function.getExtensionReceiverParameter() != null ? 1 : 0)
521            );
522            MemberScope scope = functionClass.getDefaultType().getMemberScope();
523            return scope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).iterator().next();
524        }
525    }