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.state;
018    
019    import com.intellij.openapi.util.text.StringUtil;
020    import com.intellij.psi.PsiElement;
021    import kotlin.Pair;
022    import kotlin.Unit;
023    import kotlin.collections.CollectionsKt;
024    import kotlin.jvm.functions.Function3;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
028    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
029    import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
030    import org.jetbrains.kotlin.codegen.*;
031    import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
032    import org.jetbrains.kotlin.codegen.binding.MutableClosure;
033    import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory;
034    import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
035    import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
036    import org.jetbrains.kotlin.descriptors.*;
037    import org.jetbrains.kotlin.fileClasses.FileClasses;
038    import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
039    import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
040    import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
041    import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
042    import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo;
043    import org.jetbrains.kotlin.load.java.JvmAbi;
044    import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion;
045    import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
046    import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
047    import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
048    import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
049    import org.jetbrains.kotlin.load.kotlin.*;
050    import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
051    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
052    import org.jetbrains.kotlin.name.ClassId;
053    import org.jetbrains.kotlin.name.FqName;
054    import org.jetbrains.kotlin.name.Name;
055    import org.jetbrains.kotlin.name.SpecialNames;
056    import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
057    import org.jetbrains.kotlin.psi.KtExpression;
058    import org.jetbrains.kotlin.psi.KtFile;
059    import org.jetbrains.kotlin.psi.KtFunctionLiteral;
060    import org.jetbrains.kotlin.psi.KtLambdaExpression;
061    import org.jetbrains.kotlin.resolve.*;
062    import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
063    import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
064    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
065    import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
066    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
067    import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
068    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
069    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
070    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
071    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
072    import org.jetbrains.kotlin.serialization.deserialization.DeserializedType;
073    import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
074    import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
075    import org.jetbrains.kotlin.types.*;
076    import org.jetbrains.kotlin.util.OperatorNameConventions;
077    import org.jetbrains.org.objectweb.asm.Type;
078    import org.jetbrains.org.objectweb.asm.commons.Method;
079    
080    import java.util.Collection;
081    import java.util.List;
082    
083    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
084    import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
085    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
086    import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
087    import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
088    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
089    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
090    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
091    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
092    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
093    
094    public class KotlinTypeMapper {
095        private final BindingContext bindingContext;
096        private final ClassBuilderMode classBuilderMode;
097        private final JvmFileClassesProvider fileClassesProvider;
098        private final IncrementalCache incrementalCache;
099        private final IncompatibleClassTracker incompatibleClassTracker;
100        private final String moduleName;
101        private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
102            @NotNull
103            @Override
104            public KotlinType commonSupertype(@NotNull Collection<KotlinType> types) {
105                return CommonSupertypes.commonSupertype(types);
106            }
107    
108            @Nullable
109            @Override
110            public Type getPredefinedTypeForClass(@NotNull ClassDescriptor classDescriptor) {
111                return bindingContext.get(ASM_TYPE, classDescriptor);
112            }
113    
114            @Override
115            public void processErrorType(@NotNull KotlinType kotlinType, @NotNull ClassDescriptor descriptor) {
116                if (classBuilderMode.generateBodies) {
117                    throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor));
118                }
119            }
120        };
121    
122        public KotlinTypeMapper(
123                @NotNull BindingContext bindingContext,
124                @NotNull ClassBuilderMode classBuilderMode,
125                @NotNull JvmFileClassesProvider fileClassesProvider,
126                @Nullable IncrementalCache incrementalCache,
127                @NotNull IncompatibleClassTracker incompatibleClassTracker,
128                @NotNull String moduleName
129        ) {
130            this.bindingContext = bindingContext;
131            this.classBuilderMode = classBuilderMode;
132            this.fileClassesProvider = fileClassesProvider;
133            this.incrementalCache = incrementalCache;
134            this.incompatibleClassTracker = incompatibleClassTracker;
135            this.moduleName = moduleName;
136        }
137    
138        @NotNull
139        public BindingContext getBindingContext() {
140            return bindingContext;
141        }
142    
143        @NotNull
144        public Type mapOwner(@NotNull DeclarationDescriptor descriptor) {
145            return mapOwner(descriptor, true);
146        }
147    
148        public Type mapImplementationOwner(@NotNull DeclarationDescriptor descriptor) {
149            return mapOwner(descriptor, false);
150        }
151    
152        @NotNull
153        public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean publicFacade) {
154            if (isLocalFunction(descriptor)) {
155                return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
156            }
157    
158            DeclarationDescriptor container = descriptor.getContainingDeclaration();
159            if (container instanceof PackageFragmentDescriptor) {
160                String packageMemberOwner = internalNameForPackageMemberOwner((CallableMemberDescriptor) descriptor, publicFacade);
161                return Type.getObjectType(packageMemberOwner);
162            }
163            else if (container instanceof ClassDescriptor) {
164                return mapClass((ClassDescriptor) container);
165            }
166            else {
167                throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
168            }
169        }
170    
171        @NotNull
172        private String internalNameForPackageMemberOwner(@NotNull CallableMemberDescriptor descriptor, boolean publicFacade) {
173            boolean isAccessor = descriptor instanceof AccessorForCallableDescriptor;
174            if (isAccessor) {
175                descriptor = ((AccessorForCallableDescriptor) descriptor).getCalleeDescriptor();
176            }
177            KtFile file = DescriptorToSourceUtils.getContainingFile(descriptor);
178            if (file != null) {
179                Visibility visibility = descriptor.getVisibility();
180                if (!publicFacade ||
181                    isNonConstProperty(descriptor) ||
182                    Visibilities.isPrivate(visibility) ||
183                    isAccessor/*Cause of KT-9603*/
184                ) {
185                    return FileClasses.getFileClassInternalName(fileClassesProvider, file);
186                }
187                else {
188                    return FileClasses.getFacadeClassInternalName(fileClassesProvider, file);
189                }
190            }
191    
192            CallableMemberDescriptor directMember = getDirectMember(descriptor);
193    
194            if (directMember instanceof DeserializedCallableMemberDescriptor) {
195                String facadeFqName = getPackageMemberOwnerInternalName((DeserializedCallableMemberDescriptor) directMember, publicFacade);
196                if (facadeFqName != null) return facadeFqName;
197            }
198    
199            throw new RuntimeException("Could not find package member for " + descriptor +
200                                       " in package fragment " + descriptor.getContainingDeclaration());
201        }
202    
203        private static boolean isNonConstProperty(@NotNull CallableMemberDescriptor descriptor) {
204            if (!(descriptor instanceof PropertyDescriptor)) return false;
205            PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
206            return !propertyDescriptor.isConst();
207        }
208    
209        public static class ContainingClassesInfo {
210            private final ClassId facadeClassId;
211            private final ClassId implClassId;
212    
213            public ContainingClassesInfo(ClassId facadeClassId, ClassId implClassId) {
214                this.facadeClassId = facadeClassId;
215                this.implClassId = implClassId;
216            }
217    
218            public ClassId getFacadeClassId() {
219                return facadeClassId;
220            }
221    
222            public ClassId getImplClassId() {
223                return implClassId;
224            }
225    
226            private static @Nullable ContainingClassesInfo forPackageMemberOrNull(
227                    @NotNull FqName packageFqName,
228                    @Nullable String facadeClassName,
229                    @Nullable String implClassName
230            ) {
231                if (facadeClassName == null || implClassName == null) {
232                    return null;
233                }
234                return new ContainingClassesInfo(ClassId.topLevel(packageFqName.child(Name.identifier(facadeClassName))),
235                                                 ClassId.topLevel(packageFqName.child(Name.identifier(implClassName))));
236            }
237    
238            private static @Nullable ContainingClassesInfo forClassMemberOrNull(@Nullable ClassId classId) {
239                if (classId == null) {
240                    return null;
241                }
242                return new ContainingClassesInfo(classId, classId);
243            }
244        }
245    
246        public ContainingClassesInfo getContainingClassesForDeserializedCallable(DeserializedCallableMemberDescriptor deserializedDescriptor) {
247            DeclarationDescriptor parentDeclaration = deserializedDescriptor.getContainingDeclaration();
248            ContainingClassesInfo containingClassesInfo;
249            if (parentDeclaration instanceof PackageFragmentDescriptor) {
250                containingClassesInfo = getPackageMemberContainingClassesInfo(deserializedDescriptor);
251            } else {
252                ClassId classId = getContainerClassIdForClassDescriptor((ClassDescriptor) parentDeclaration);
253                containingClassesInfo = ContainingClassesInfo.forClassMemberOrNull(classId);
254            }
255            if (containingClassesInfo == null) {
256                throw new IllegalStateException("Couldn't find container for " + deserializedDescriptor.getName());
257            }
258            return containingClassesInfo;
259        }
260    
261        private static ClassId getContainerClassIdForClassDescriptor(ClassDescriptor classDescriptor) {
262            ClassId classId = DescriptorUtilsKt.getClassId(classDescriptor);
263            if (isInterface(classDescriptor)) {
264                FqName relativeClassName = classId.getRelativeClassName();
265                //TODO test nested trait fun inlining
266                classId = new ClassId(classId.getPackageFqName(), Name.identifier(relativeClassName.shortName().asString() + JvmAbi.DEFAULT_IMPLS_SUFFIX));
267            }
268            return classId;
269        }
270    
271        @Nullable
272        private String getPackageMemberOwnerInternalName(@NotNull DeserializedCallableMemberDescriptor descriptor, boolean publicFacade) {
273            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
274            assert containingDeclaration instanceof PackageFragmentDescriptor : "Not a top-level member: " + descriptor;
275    
276            ContainingClassesInfo containingClasses = getPackageMemberContainingClassesInfo(descriptor);
277            if (containingClasses == null) {
278                return null;
279            }
280    
281            ClassId ownerClassId = publicFacade ? containingClasses.getFacadeClassId()
282                                                : containingClasses.getImplClassId();
283            return JvmClassName.byClassId(ownerClassId).getInternalName();
284        }
285    
286        private static final ClassId FAKE_CLASS_ID_FOR_BUILTINS = ClassId.topLevel(new FqName("kotlin.KotlinPackage"));
287    
288        @Nullable
289        private ContainingClassesInfo getPackageMemberContainingClassesInfo(@NotNull DeserializedCallableMemberDescriptor descriptor) {
290            // XXX This method is a dirty hack.
291            // We need some safe, concise way to identify multifile facade and multifile part
292            // from a deserialized package member descriptor.
293            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
294            assert containingDeclaration instanceof PackageFragmentDescriptor
295                    : "Package member expected, got " + descriptor + " in " + containingDeclaration;
296            PackageFragmentDescriptor packageFragmentDescriptor = (PackageFragmentDescriptor) containingDeclaration;
297    
298            if (packageFragmentDescriptor instanceof BuiltInsPackageFragment) {
299                return new ContainingClassesInfo(FAKE_CLASS_ID_FOR_BUILTINS, FAKE_CLASS_ID_FOR_BUILTINS);
300            }
301    
302            Name implClassName = JvmFileClassUtil.getImplClassName(descriptor);
303            assert implClassName != null : "No implClassName for " + descriptor;
304            String implSimpleName = implClassName.asString();
305    
306            String facadeSimpleName;
307    
308            if (packageFragmentDescriptor instanceof LazyJavaPackageFragment) {
309                facadeSimpleName = ((LazyJavaPackageFragment) packageFragmentDescriptor).getFacadeSimpleNameForPartSimpleName(
310                        implClassName.asString()
311                );
312            }
313            else if (packageFragmentDescriptor instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment) {
314                assert incrementalCache != null
315                        : "IncrementalPackageFragment found outside of incremental compilation context " +
316                          "for " + descriptor + " in package " + packageFragmentDescriptor;
317    
318                String implClassInternalName = internalNameByFqNameWithoutInnerClasses(
319                        packageFragmentDescriptor.getFqName().child(implClassName));
320                String facadeClassInternalName = incrementalCache.getMultifileFacade(implClassInternalName);
321                if (facadeClassInternalName == null) {
322                    facadeSimpleName = implClassName.asString();
323                }
324                else {
325                    facadeSimpleName = getSimpleInternalName(facadeClassInternalName);
326                }
327            }
328            else {
329                throw new AssertionError("Unexpected package fragment for " + descriptor + ": " +
330                                         packageFragmentDescriptor + " (" + packageFragmentDescriptor.getClass().getSimpleName() + ")");
331            }
332            return ContainingClassesInfo.forPackageMemberOrNull(packageFragmentDescriptor.getFqName(), facadeSimpleName, implSimpleName);
333        }
334    
335        @NotNull
336        public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
337            return mapReturnType(descriptor, null);
338        }
339    
340        @NotNull
341        private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable JvmSignatureWriter sw) {
342            KotlinType returnType = descriptor.getReturnType();
343            assert returnType != null : "Function has no return type: " + descriptor;
344    
345            if (descriptor instanceof ConstructorDescriptor) {
346                return Type.VOID_TYPE;
347            }
348    
349            if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) {
350                if (sw != null) {
351                    sw.writeAsmType(Type.VOID_TYPE);
352                }
353                return Type.VOID_TYPE;
354            }
355            else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
356                // GENERIC_TYPE is a hack to automatically box the return type
357                //noinspection ConstantConditions
358                return mapType(descriptor.getReturnType(), sw, TypeMappingMode.GENERIC_ARGUMENT);
359            }
360    
361            return mapReturnType(descriptor, sw, returnType);
362        }
363    
364        @NotNull
365        private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable JvmSignatureWriter sw, @NotNull KotlinType returnType) {
366            boolean isAnnotationMethod = DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration());
367            if (sw == null || sw.skipGenericSignature()) {
368                return mapType(returnType, sw, TypeMappingMode.getModeForReturnTypeNoGeneric(isAnnotationMethod));
369            }
370    
371            TypeMappingMode typeMappingModeFromAnnotation =
372                    TypeMappingUtil.extractTypeMappingModeFromAnnotation(descriptor, returnType, isAnnotationMethod);
373            if (typeMappingModeFromAnnotation != null) {
374                return mapType(returnType, sw, typeMappingModeFromAnnotation);
375            }
376    
377            TypeMappingMode mappingMode = TypeMappingMode.getOptimalModeForReturnType(
378                    returnType,
379                    /* isAnnotationMethod = */ isAnnotationMethod);
380    
381            return mapType(returnType, sw, mappingMode);
382        }
383    
384        @NotNull
385        public Type mapSupertype(@NotNull KotlinType jetType, @Nullable JvmSignatureWriter signatureVisitor) {
386            return mapType(jetType, signatureVisitor, TypeMappingMode.SUPER_TYPE);
387        }
388    
389        @NotNull
390        public Type mapTypeParameter(@NotNull KotlinType jetType, @Nullable JvmSignatureWriter signatureVisitor) {
391            return mapType(jetType, signatureVisitor, TypeMappingMode.GENERIC_ARGUMENT);
392        }
393    
394        @NotNull
395        public Type mapClass(@NotNull ClassifierDescriptor classifier) {
396            return mapType(classifier.getDefaultType(), null, TypeMappingMode.DEFAULT);
397        }
398    
399        @NotNull
400        public Type mapType(@NotNull KotlinType jetType) {
401            return mapType(jetType, null, TypeMappingMode.DEFAULT);
402        }
403    
404        @NotNull
405        public Type mapType(@NotNull CallableDescriptor descriptor) {
406            //noinspection ConstantConditions
407            return mapType(descriptor.getReturnType());
408        }
409    
410        @NotNull
411        public JvmMethodGenericSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
412            JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
413            sw.writeReturnType();
414            mapType(descriptor.getType(), sw, TypeMappingMode.VALUE_FOR_ANNOTATION);
415            sw.writeReturnTypeEnd();
416            return sw.makeJvmMethodSignature(descriptor.getName().asString());
417        }
418    
419        @NotNull
420        public Type mapType(@NotNull ClassifierDescriptor descriptor) {
421            return mapType(descriptor.getDefaultType());
422        }
423    
424        @NotNull
425        private Type mapType(
426                @NotNull KotlinType kotlinType,
427                @Nullable final JvmSignatureWriter signatureVisitor,
428                @NotNull TypeMappingMode mode
429        ) {
430            return TypeSignatureMappingKt.mapType(
431                    kotlinType, AsmTypeFactory.INSTANCE, mode, typeMappingConfiguration, signatureVisitor,
432                    new Function3<KotlinType, Type, TypeMappingMode, Unit>() {
433                        @Override
434                        public Unit invoke(KotlinType kotlinType, Type type, TypeMappingMode mode) {
435                            writeGenericType(kotlinType, type, signatureVisitor, mode);
436                            return Unit.INSTANCE;
437                        }
438                    });
439        }
440    
441        @NotNull
442        public Type mapDefaultImpls(@NotNull ClassDescriptor descriptor) {
443            return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.DEFAULT_IMPLS_SUFFIX);
444        }
445    
446        @NotNull
447        private static String generateErrorMessageForErrorType(@NotNull KotlinType type, @NotNull DeclarationDescriptor descriptor) {
448            PsiElement declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
449    
450            if (declarationElement == null) {
451                String message = "Error type encountered: %s (%s).";
452                if (FlexibleTypesKt.upperIfFlexible(type) instanceof DeserializedType) {
453                    message +=
454                            " One of the possible reasons may be that this type is not directly accessible from this module. " +
455                            "To workaround this error, try adding an explicit dependency on the module or library which contains this type " +
456                            "to the classpath";
457                }
458                return String.format(message, type, type.getClass().getSimpleName());
459            }
460    
461            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
462            PsiElement parentDeclarationElement =
463                    containingDeclaration != null ? DescriptorToSourceUtils.descriptorToDeclaration(containingDeclaration) : null;
464    
465            return String.format(
466                    "Error type encountered: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
467                    type,
468                    type.getClass().getSimpleName(),
469                    descriptor,
470                    declarationElement,
471                    declarationElement.getText(),
472                    parentDeclarationElement,
473                    parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"
474            );
475        }
476    
477        private void writeGenericType(
478                @NotNull KotlinType type,
479                @NotNull Type asmType,
480                @Nullable JvmSignatureWriter signatureVisitor,
481                @NotNull TypeMappingMode mode
482        ) {
483            if (signatureVisitor != null) {
484    
485                // Nothing mapping rules:
486                //  Map<Nothing, Foo> -> Map
487                //  Map<Foo, List<Nothing>> -> Map<Foo, List>
488                //  In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
489                //  In<Nothing, Nothing> -> In
490                //  Inv<in Nothing, Foo> -> Inv
491                if (signatureVisitor.skipGenericSignature() || hasNothingInNonContravariantPosition(type) || type.getArguments().isEmpty()) {
492                    signatureVisitor.writeAsmType(asmType);
493                    return;
494                }
495    
496                PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
497                assert possiblyInnerType != null : "possiblyInnerType with arguments should not be null";
498    
499                List<PossiblyInnerType> innerTypesAsList = possiblyInnerType.segments();
500                PossiblyInnerType outermostInnerType = innerTypesAsList.get(0);
501                ClassDescriptor outermostClass = outermostInnerType.getClassDescriptor();
502    
503                if (innerTypesAsList.size() == 1) {
504                    signatureVisitor.writeClassBegin(asmType);
505                }
506                else {
507                    signatureVisitor.writeOuterClassBegin(
508                            asmType,
509                            mapType(outermostClass.getDefaultType()).getInternalName());
510                }
511    
512                writeGenericArguments(
513                        signatureVisitor,
514                        outermostInnerType.getArguments(), outermostClass.getDeclaredTypeParameters(), mode);
515    
516                for (PossiblyInnerType innerPart : innerTypesAsList.subList(1, innerTypesAsList.size())) {
517                    ClassDescriptor classDescriptor = innerPart.getClassDescriptor();
518                    signatureVisitor.writeInnerClass(getJvmShortName(classDescriptor));
519                    writeGenericArguments(
520                            signatureVisitor, innerPart.getArguments(),
521                            classDescriptor.getDeclaredTypeParameters(), mode);
522                }
523    
524                signatureVisitor.writeClassEnd();
525            }
526        }
527    
528        @Nullable
529        private static String getJvmShortName(@NotNull ClassDescriptor klass) {
530            ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(DescriptorUtils.getFqName(klass));
531            if (classId != null) {
532                return classId.getShortClassName().asString();
533            }
534    
535            return SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
536        }
537    
538        private void writeGenericArguments(
539                @NotNull JvmSignatureWriter signatureVisitor,
540                @NotNull List<? extends TypeProjection> arguments,
541                @NotNull List<? extends TypeParameterDescriptor> parameters,
542                @NotNull TypeMappingMode mode
543        ) {
544            for (Pair<? extends TypeParameterDescriptor, ? extends TypeProjection> item : CollectionsKt.zip(parameters, arguments)) {
545                TypeParameterDescriptor parameter = item.getFirst();
546                TypeProjection argument = item.getSecond();
547    
548                if (
549                    argument.isStarProjection() ||
550                    // In<Nothing, Foo> == In<*, Foo> -> In<?, Foo>
551                    KotlinBuiltIns.isNothing(argument.getType()) && parameter.getVariance() == Variance.IN_VARIANCE
552                ) {
553                    signatureVisitor.writeUnboundedWildcard();
554                }
555                else {
556                    TypeMappingMode argumentMode = TypeMappingUtil.updateArgumentModeFromAnnotations(mode, argument.getType());
557                    Variance projectionKind = getVarianceForWildcard(parameter, argument, argumentMode);
558    
559                    signatureVisitor.writeTypeArgument(projectionKind);
560    
561                    mapType(argument.getType(), signatureVisitor,
562                            argumentMode.toGenericArgumentMode(
563                                    TypeMappingUtil.getEffectiveVariance(parameter.getVariance(), argument.getProjectionKind())));
564    
565                    signatureVisitor.writeTypeArgumentEnd();
566                }
567            }
568        }
569    
570        private static boolean hasNothingInNonContravariantPosition(KotlinType kotlinType) {
571            List<TypeParameterDescriptor> parameters = kotlinType.getConstructor().getParameters();
572            List<TypeProjection> arguments = kotlinType.getArguments();
573    
574            for (int i = 0; i < arguments.size(); i++) {
575                TypeProjection projection = arguments.get(i);
576    
577                if (projection.isStarProjection()) continue;
578    
579                KotlinType type = projection.getType();
580    
581                if (KotlinBuiltIns.isNullableNothing(type) ||
582                    KotlinBuiltIns.isNothing(type) && parameters.get(i).getVariance() != Variance.IN_VARIANCE) return true;
583            }
584    
585            return false;
586        }
587    
588        @NotNull
589        private static Variance getVarianceForWildcard(
590                @NotNull TypeParameterDescriptor parameter,
591                @NotNull TypeProjection projection,
592                @NotNull TypeMappingMode mode
593        ) {
594            Variance projectionKind = projection.getProjectionKind();
595            Variance parameterVariance = parameter.getVariance();
596    
597            if (parameterVariance == Variance.INVARIANT) {
598                return projectionKind;
599            }
600    
601            if (mode.getSkipDeclarationSiteWildcards()) {
602                return Variance.INVARIANT;
603            }
604    
605            if (projectionKind == Variance.INVARIANT || projectionKind == parameterVariance) {
606                if (mode.getSkipDeclarationSiteWildcardsIfPossible() && !projection.isStarProjection()) {
607                    if (parameterVariance == Variance.OUT_VARIANCE && TypeMappingUtil.isMostPreciseCovariantArgument(projection.getType())){
608                        return Variance.INVARIANT;
609                    }
610    
611                    if (parameterVariance == Variance.IN_VARIANCE
612                        && TypeMappingUtil.isMostPreciseContravariantArgument(projection.getType(), parameter)) {
613                        return Variance.INVARIANT;
614                    }
615                }
616                return parameterVariance;
617            }
618    
619            // In<out X> = In<*>
620            // Out<in X> = Out<*>
621            return Variance.OUT_VARIANCE;
622        }
623    
624        @NotNull
625        public CallableMethod mapToCallableMethod(@NotNull FunctionDescriptor descriptor, boolean superCall) {
626            if (descriptor instanceof ConstructorDescriptor) {
627                JvmMethodSignature method = mapSignatureSkipGeneric(descriptor);
628                Type owner = mapClass(((ConstructorDescriptor) descriptor).getContainingDeclaration());
629                String defaultImplDesc = mapDefaultMethod(descriptor, OwnerKind.IMPLEMENTATION).getDescriptor();
630                return new CallableMethod(owner, owner, defaultImplDesc, method, INVOKESPECIAL, null, null, null);
631            }
632    
633            DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
634    
635            FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
636    
637            JvmMethodSignature signature;
638            Type owner;
639            Type ownerForDefaultImpl;
640            FunctionDescriptor baseMethodDescriptor;
641            int invokeOpcode;
642            Type thisClass;
643    
644            if (functionParent instanceof ClassDescriptor) {
645                FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
646    
647                ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
648                ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
649    
650                boolean originalIsInterface = isJvmInterface(declarationOwner);
651                boolean currentIsInterface = isJvmInterface(currentOwner);
652    
653                boolean isInterface = currentIsInterface && originalIsInterface;
654    
655                baseMethodDescriptor = findBaseDeclaration(functionDescriptor).getOriginal();
656                ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
657                ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
658    
659                if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
660                    thisClass = mapClass(currentOwner);
661                    if (declarationOwner instanceof JavaClassDescriptor) {
662                        invokeOpcode = INVOKESPECIAL;
663                        signature = mapSignatureSkipGeneric(functionDescriptor);
664                        owner = thisClass;
665                    }
666                    else {
667                        invokeOpcode = INVOKESTATIC;
668                        signature = mapSignatureSkipGeneric(descriptor.getOriginal(), OwnerKind.DEFAULT_IMPLS);
669                        owner = mapDefaultImpls(currentOwner);
670                    }
671                }
672                else {
673                    boolean isStaticInvocation = (isStaticDeclaration(functionDescriptor) &&
674                                                  !(functionDescriptor instanceof ImportedFromObjectCallableDescriptor)) ||
675                                                 isStaticAccessor(functionDescriptor) ||
676                                                 AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor);
677                    if (isStaticInvocation) {
678                        invokeOpcode = INVOKESTATIC;
679                    }
680                    else if (isInterface) {
681                        invokeOpcode = INVOKEINTERFACE;
682                    }
683                    else {
684                        boolean isPrivateFunInvocation = Visibilities.isPrivate(functionDescriptor.getVisibility());
685                        invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
686                    }
687    
688                    FunctionDescriptor overriddenSpecialBuiltinFunction =
689                            SpecialBuiltinMembers.<FunctionDescriptor>getOverriddenBuiltinReflectingJvmDescriptor(functionDescriptor.getOriginal());
690                    FunctionDescriptor functionToCall = overriddenSpecialBuiltinFunction != null && !superCall
691                                                        ? overriddenSpecialBuiltinFunction.getOriginal()
692                                                        : functionDescriptor.getOriginal();
693    
694                    signature = mapSignatureSkipGeneric(functionToCall);
695    
696                    ClassDescriptor receiver = (currentIsInterface && !originalIsInterface) || currentOwner instanceof FunctionClassDescriptor
697                                               ? declarationOwner
698                                               : currentOwner;
699                    owner = mapClass(receiver);
700                    thisClass = owner;
701                }
702            }
703            else {
704                signature = mapSignatureSkipGeneric(functionDescriptor.getOriginal());
705                owner = mapOwner(functionDescriptor);
706                ownerForDefaultImpl = owner;
707                baseMethodDescriptor = functionDescriptor;
708                if (functionParent instanceof PackageFragmentDescriptor) {
709                    invokeOpcode = INVOKESTATIC;
710                    thisClass = null;
711                }
712                else if (functionDescriptor instanceof ConstructorDescriptor) {
713                    invokeOpcode = INVOKESPECIAL;
714                    thisClass = null;
715                }
716                else {
717                    invokeOpcode = INVOKEVIRTUAL;
718                    thisClass = owner;
719                }
720            }
721    
722            Type calleeType = isLocalFunction(functionDescriptor) ? owner : null;
723    
724            Type receiverParameterType;
725            ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getExtensionReceiverParameter();
726            if (receiverParameter != null) {
727                receiverParameterType = mapType(receiverParameter.getType());
728            }
729            else {
730                receiverParameterType = null;
731            }
732    
733            String defaultImplDesc = mapDefaultMethod(baseMethodDescriptor, getKindForDefaultImplCall(baseMethodDescriptor)).getDescriptor();
734    
735            return new CallableMethod(
736                    owner, ownerForDefaultImpl, defaultImplDesc, signature, invokeOpcode,
737                    thisClass, receiverParameterType, calleeType);
738        }
739    
740        public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
741            return descriptor instanceof AccessorForCallableDescriptor<?>;
742        }
743    
744        public static boolean isStaticAccessor(@NotNull CallableMemberDescriptor descriptor) {
745            if (descriptor instanceof AccessorForConstructorDescriptor) return false;
746            return isAccessor(descriptor);
747        }
748    
749        @NotNull
750        private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
751            if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
752                return function;
753            }
754            return findBaseDeclaration(function);
755        }
756    
757        @NotNull
758        private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
759            if (function.getOverriddenDescriptors().isEmpty()) {
760                return function;
761            }
762            else {
763                // TODO: prefer class to interface
764                return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
765            }
766        }
767    
768        @NotNull
769        private String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
770            if (!(descriptor instanceof JavaCallableMemberDescriptor)) {
771                String platformName = getJvmName(descriptor);
772                if (platformName != null) return platformName;
773            }
774    
775            String nameForSpecialFunction = SpecialBuiltinMembers.getJvmMethodNameIfSpecial(descriptor);
776            if (nameForSpecialFunction != null) return nameForSpecialFunction;
777    
778            if (descriptor instanceof PropertyAccessorDescriptor) {
779                PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
780                if (isAnnotationClass(property.getContainingDeclaration())) {
781                    return property.getName().asString();
782                }
783    
784                boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
785                String propertyName = isAccessor
786                                      ? ((AccessorForPropertyDescriptor) property).getAccessorSuffix()
787                                      : property.getName().asString();
788    
789                String accessorName = descriptor instanceof PropertyGetterDescriptor
790                                      ? JvmAbi.getterName(propertyName)
791                                      : JvmAbi.setterName(propertyName);
792    
793                return mangleMemberNameIfRequired(isAccessor ? "access$" + accessorName : accessorName, descriptor);
794            }
795            else if (isFunctionLiteral(descriptor)) {
796                PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
797                if (element instanceof KtFunctionLiteral) {
798                    PsiElement expression = element.getParent();
799                    if (expression instanceof KtLambdaExpression) {
800                        SamType samType = bindingContext.get(SAM_VALUE, (KtExpression) expression);
801                        if (samType != null) {
802                            return samType.getAbstractMethod().getName().asString();
803                        }
804                    }
805                }
806    
807                return OperatorNameConventions.INVOKE.asString();
808            }
809            else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
810                return OperatorNameConventions.INVOKE.asString();
811            }
812            else {
813                return mangleMemberNameIfRequired(descriptor.getName().asString(), descriptor);
814            }
815        }
816    
817        @NotNull
818        private static OwnerKind getKindForDefaultImplCall(@NotNull FunctionDescriptor baseMethodDescriptor) {
819            DeclarationDescriptor containingDeclaration = baseMethodDescriptor.getContainingDeclaration();
820            if (containingDeclaration instanceof PackageFragmentDescriptor) {
821                return OwnerKind.PACKAGE;
822            }
823            else if (isInterface(containingDeclaration)) {
824                return OwnerKind.DEFAULT_IMPLS;
825            }
826            return OwnerKind.IMPLEMENTATION;
827        }
828    
829        @NotNull
830        public static String mapDefaultFieldName(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegated) {
831            String name;
832            if (propertyDescriptor instanceof AccessorForPropertyDescriptor) {
833                name = ((AccessorForPropertyDescriptor) propertyDescriptor).getCalleeDescriptor().getName().asString();
834            }
835            else {
836                name = propertyDescriptor.getName().asString();
837            }
838            return isDelegated ? name + JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX : name;
839        }
840    
841        @NotNull
842        private String mangleMemberNameIfRequired(@NotNull String name, @NotNull CallableMemberDescriptor descriptor) {
843            if (descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
844                //script properties should be public
845                return name;
846            }
847    
848            if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
849                if (Visibilities.isPrivate(descriptor.getVisibility()) && !(descriptor instanceof ConstructorDescriptor) && !"<clinit>".equals(name)) {
850                    KtFile containingFile = DescriptorToSourceUtils.getContainingFile(descriptor);
851                    assert containingFile != null : "Private descriptor accessed outside of corresponding file scope: " + descriptor;
852                    JvmFileClassInfo fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(containingFile);
853                    if (fileClassInfo.getWithJvmMultifileClass()) {
854                        return name + "$" + fileClassInfo.getFileClassFqName().shortName().asString();
855                    }
856                }
857                return name;
858            }
859    
860            if (!(descriptor instanceof ConstructorDescriptor) && descriptor.getVisibility() == Visibilities.INTERNAL) {
861                return name + "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName);
862            }
863    
864            return name;
865        }
866    
867        @NotNull
868        public Method mapAsmMethod(@NotNull FunctionDescriptor descriptor) {
869            return mapSignature(descriptor, true).getAsmMethod();
870        }
871    
872        @NotNull
873        public Method mapAsmMethod(@NotNull FunctionDescriptor descriptor, @NotNull OwnerKind kind) {
874            return mapSignature(descriptor, kind, true).getAsmMethod();
875        }
876    
877        @NotNull
878        private JvmMethodGenericSignature mapSignature(@NotNull FunctionDescriptor f, boolean skipGenericSignature) {
879            return mapSignature(f, OwnerKind.IMPLEMENTATION, skipGenericSignature);
880        }
881    
882        @NotNull
883        public JvmMethodSignature mapSignatureSkipGeneric(@NotNull FunctionDescriptor f) {
884            return mapSignatureSkipGeneric(f, OwnerKind.IMPLEMENTATION);
885        }
886    
887        @NotNull
888        public JvmMethodSignature mapSignatureSkipGeneric(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
889            return mapSignature(f, kind, true);
890        }
891    
892        @NotNull
893        public JvmMethodGenericSignature mapSignatureWithGeneric(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
894            return mapSignature(f, kind, false);
895        }
896    
897        @NotNull
898        private JvmMethodGenericSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind, boolean skipGenericSignature) {
899            if (f.getInitialSignatureDescriptor() != null && f != f.getInitialSignatureDescriptor()) {
900                // Overrides of special builtin in Kotlin classes always have special signature
901                if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(f) == null ||
902                    f.getContainingDeclaration().getOriginal() instanceof JavaClassDescriptor) {
903                    return mapSignature(f.getInitialSignatureDescriptor(), kind, skipGenericSignature);
904                }
905            }
906    
907            if (f instanceof ConstructorDescriptor) {
908                return mapSignature(f, kind, f.getOriginal().getValueParameters(), skipGenericSignature);
909            }
910    
911            return mapSignature(f, kind, f.getValueParameters(), skipGenericSignature);
912        }
913    
914        @NotNull
915        public JvmMethodGenericSignature mapSignature(
916                @NotNull FunctionDescriptor f,
917                @NotNull OwnerKind kind,
918                @NotNull List<ValueParameterDescriptor> valueParameters,
919                boolean skipGenericSignature
920        ) {
921            if (f instanceof FunctionImportedFromObject) {
922                return mapSignature(((FunctionImportedFromObject) f).getCallableFromObject(), kind, skipGenericSignature);
923            }
924    
925            checkOwnerCompatibility(f);
926    
927            JvmSignatureWriter sw = skipGenericSignature || f instanceof AccessorForCallableDescriptor
928                                     ? new JvmSignatureWriter()
929                                     : new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
930    
931            if (f instanceof ConstructorDescriptor) {
932                sw.writeParametersStart();
933                writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
934    
935                for (ValueParameterDescriptor parameter : valueParameters) {
936                    writeParameter(sw, parameter.getType(), f);
937                }
938    
939                if (f instanceof AccessorForConstructorDescriptor) {
940                    writeParameter(sw, JvmMethodParameterKind.CONSTRUCTOR_MARKER, DEFAULT_CONSTRUCTOR_MARKER);
941                }
942    
943                writeVoidReturn(sw);
944            }
945            else {
946                CallableMemberDescriptor directMember = getDirectMember(f);
947                KotlinType thisIfNeeded = null;
948                if (OwnerKind.DEFAULT_IMPLS == kind) {
949                    ReceiverTypeAndTypeParameters receiverTypeAndTypeParameters = TypeMapperUtilsKt.patchTypeParametersForDefaultImplMethod(directMember);
950                    writeFormalTypeParameters(CollectionsKt.plus(receiverTypeAndTypeParameters.getTypeParameters(), directMember.getTypeParameters()), sw);
951                    thisIfNeeded = receiverTypeAndTypeParameters.getReceiverType();
952                }
953                else {
954                    writeFormalTypeParameters(directMember.getTypeParameters(), sw);
955                    if (isAccessor(f) && f.getDispatchReceiverParameter() != null) {
956                        thisIfNeeded = ((ClassDescriptor) f.getContainingDeclaration()).getDefaultType();
957                    }
958                }
959    
960                sw.writeParametersStart();
961                if (thisIfNeeded != null) {
962                    writeParameter(sw, JvmMethodParameterKind.THIS, thisIfNeeded, f);
963                }
964    
965                ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
966                if (receiverParameter != null) {
967                    writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType(), f);
968                }
969    
970                for (ValueParameterDescriptor parameter : valueParameters) {
971                    boolean forceBoxing = MethodSignatureMappingKt.forceSingleValueParameterBoxing(f);
972                    writeParameter(
973                            sw,
974                            forceBoxing ? TypeUtils.makeNullable(parameter.getType()) : parameter.getType(),
975                            f
976                    );
977                }
978    
979                sw.writeReturnType();
980                mapReturnType(f, sw);
981                sw.writeReturnTypeEnd();
982            }
983    
984            JvmMethodGenericSignature signature = sw.makeJvmMethodSignature(mapFunctionName(f));
985    
986            if (kind != OwnerKind.DEFAULT_IMPLS) {
987                SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
988    
989                if (specialSignatureInfo != null) {
990                    String newGenericSignature = CodegenUtilKt.replaceValueParametersIn(
991                            specialSignatureInfo, signature.getGenericsSignature());
992                    return new JvmMethodGenericSignature(signature.getAsmMethod(), signature.getValueParameters(), newGenericSignature);
993                }
994            }
995    
996            return signature;
997        }
998    
999        private void checkOwnerCompatibility(@NotNull FunctionDescriptor descriptor) {
1000            if (!(descriptor instanceof DeserializedCallableMemberDescriptor)) return;
1001    
1002            KotlinJvmBinaryClass ownerClass = null;
1003    
1004            DeclarationDescriptor container = descriptor.getContainingDeclaration();
1005            if (container instanceof DeserializedClassDescriptor) {
1006                SourceElement source = ((DeserializedClassDescriptor) container).getSource();
1007                if (source instanceof KotlinJvmBinarySourceElement) {
1008                    ownerClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
1009                }
1010            }
1011            else if (container instanceof LazyJavaPackageFragment) {
1012                SourceElement source = ((LazyJavaPackageFragment) container).getSource();
1013                if (source instanceof KotlinJvmBinaryPackageSourceElement) {
1014                    ownerClass = ((KotlinJvmBinaryPackageSourceElement) source).getRepresentativeBinaryClass();
1015                }
1016            }
1017    
1018            if (ownerClass != null) {
1019                JvmBytecodeBinaryVersion version = ownerClass.getClassHeader().getBytecodeVersion();
1020                if (!version.isCompatible()) {
1021                    incompatibleClassTracker.record(ownerClass);
1022                }
1023            }
1024        }
1025    
1026        @NotNull
1027        private static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
1028            String descriptor = method.getDescriptor();
1029            int argumentsCount = Type.getArgumentTypes(descriptor).length;
1030            if (isExtension) {
1031                argumentsCount--;
1032            }
1033            int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
1034            String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
1035            additionalArgs += (isConstructor(method) ? DEFAULT_CONSTRUCTOR_MARKER : OBJECT_TYPE).getDescriptor();
1036            String result = descriptor.replace(")", additionalArgs + ")");
1037            if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
1038                return result.replace("(", "(" + dispatchReceiverDescriptor);
1039            }
1040            return result;
1041        }
1042    
1043        public ClassBuilderMode getClassBuilderMode() {
1044            return classBuilderMode;
1045        }
1046    
1047        private static boolean isConstructor(@NotNull Method method) {
1048            return "<init>".equals(method.getName());
1049        }
1050    
1051        @NotNull
1052        public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind) {
1053            Method jvmSignature = mapAsmMethod(functionDescriptor, kind);
1054            Type ownerType = mapOwner(functionDescriptor);
1055            boolean isConstructor = isConstructor(jvmSignature);
1056            String descriptor = getDefaultDescriptor(
1057                    jvmSignature,
1058                    isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
1059                    functionDescriptor.getExtensionReceiverParameter() != null
1060            );
1061    
1062            return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
1063        }
1064    
1065        /**
1066         * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
1067         * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
1068         * with a non-primitive return type. In that case the generated method's return type should be boxed: otherwise it's not possible to use
1069         * this class from Java since javac issues errors when loading the class (incompatible return types)
1070         */
1071        private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
1072            //noinspection ConstantConditions
1073            if (!KotlinBuiltIns.isPrimitiveType(descriptor.getReturnType())) return false;
1074    
1075            for (FunctionDescriptor overridden : getAllOverriddenDescriptors(descriptor)) {
1076                //noinspection ConstantConditions
1077                if (!KotlinBuiltIns.isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
1078            }
1079    
1080            return false;
1081        }
1082    
1083        private static void writeVoidReturn(@NotNull JvmSignatureWriter sw) {
1084            sw.writeReturnType();
1085            sw.writeAsmType(Type.VOID_TYPE);
1086            sw.writeReturnTypeEnd();
1087        }
1088    
1089        @Nullable
1090        public String mapFieldSignature(@NotNull KotlinType backingFieldType, @NotNull PropertyDescriptor propertyDescriptor) {
1091            JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
1092    
1093            if (!propertyDescriptor.isVar()) {
1094                mapReturnType(propertyDescriptor, sw, backingFieldType);
1095            }
1096            else {
1097                writeParameterType(sw, backingFieldType, propertyDescriptor);
1098            }
1099    
1100            return sw.makeJavaGenericSignature();
1101        }
1102    
1103        public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull JvmSignatureWriter sw) {
1104            if (sw.skipGenericSignature()) return;
1105            for (TypeParameterDescriptor typeParameter : typeParameters) {
1106                writeFormalTypeParameter(typeParameter, sw);
1107            }
1108        }
1109    
1110        private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull JvmSignatureWriter sw) {
1111            if (!classBuilderMode.generateBodies && typeParameterDescriptor.getName().isSpecial()) {
1112                // If a type parameter has no name, the code below fails, but it should recover in case of light classes
1113                return;
1114            }
1115    
1116            sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
1117    
1118            classBound:
1119            {
1120                sw.writeClassBound();
1121    
1122                for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
1123                    if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
1124                        if (!isJvmInterface(jetType)) {
1125                            mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
1126                            break classBound;
1127                        }
1128                    }
1129                }
1130    
1131                // "extends Object" is optional according to ClassFileFormat-Java5.pdf
1132                // but javac complaints to signature:
1133                // <P:>Ljava/lang/Object;
1134                // TODO: avoid writing java/lang/Object if interface list is not empty
1135            }
1136            sw.writeClassBoundEnd();
1137    
1138            for (KotlinType jetType : typeParameterDescriptor.getUpperBounds()) {
1139                ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
1140                if (classifier instanceof ClassDescriptor) {
1141                    if (isJvmInterface(jetType)) {
1142                        sw.writeInterfaceBound();
1143                        mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
1144                        sw.writeInterfaceBoundEnd();
1145                    }
1146                }
1147                else if (classifier instanceof TypeParameterDescriptor) {
1148                    sw.writeInterfaceBound();
1149                    mapType(jetType, sw, TypeMappingMode.GENERIC_ARGUMENT);
1150                    sw.writeInterfaceBoundEnd();
1151                }
1152                else {
1153                    throw new UnsupportedOperationException("Unknown classifier: " + classifier);
1154                }
1155            }
1156        }
1157    
1158        private void writeParameter(
1159                @NotNull JvmSignatureWriter sw,
1160                @NotNull KotlinType type,
1161                @Nullable CallableDescriptor callableDescriptor
1162        ) {
1163            writeParameter(sw, JvmMethodParameterKind.VALUE, type, callableDescriptor);
1164        }
1165    
1166        private void writeParameter(
1167                @NotNull JvmSignatureWriter sw,
1168                @NotNull JvmMethodParameterKind kind,
1169                @NotNull KotlinType type,
1170                @Nullable CallableDescriptor callableDescriptor
1171        ) {
1172            sw.writeParameterType(kind);
1173    
1174            writeParameterType(sw, type, callableDescriptor);
1175    
1176            sw.writeParameterTypeEnd();
1177        }
1178    
1179        private void writeParameterType(
1180                @NotNull JvmSignatureWriter sw,
1181                @NotNull KotlinType type,
1182                @Nullable CallableDescriptor callableDescriptor
1183        ) {
1184            if (sw.skipGenericSignature()) {
1185                mapType(type, sw, TypeMappingMode.DEFAULT);
1186                return;
1187            }
1188    
1189            TypeMappingMode typeMappingMode;
1190    
1191            TypeMappingMode typeMappingModeFromAnnotation =
1192                    TypeMappingUtil.extractTypeMappingModeFromAnnotation(callableDescriptor, type, /* isForAnnotationParameter = */ false);
1193    
1194            if (typeMappingModeFromAnnotation != null) {
1195                typeMappingMode = typeMappingModeFromAnnotation;
1196            }
1197            else if (TypeMappingUtil.isMethodWithDeclarationSiteWildcards(callableDescriptor) && !type.getArguments().isEmpty()) {
1198                typeMappingMode = TypeMappingMode.GENERIC_ARGUMENT; // Render all wildcards
1199            }
1200            else {
1201                typeMappingMode = TypeMappingMode.getOptimalModeForValueParameter(type);
1202            }
1203    
1204            mapType(type, sw, typeMappingMode);
1205        }
1206    
1207        private static void writeParameter(@NotNull JvmSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
1208            sw.writeParameterType(kind);
1209            sw.writeAsmType(type);
1210            sw.writeParameterTypeEnd();
1211        }
1212    
1213        private void writeAdditionalConstructorParameters(@NotNull ConstructorDescriptor descriptor, @NotNull JvmSignatureWriter sw) {
1214            MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
1215    
1216            ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
1217            if (captureThis != null) {
1218                writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
1219            }
1220    
1221            KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
1222            if (captureReceiverType != null) {
1223                writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor);
1224            }
1225    
1226            ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
1227            if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
1228                writeParameter(
1229                        sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
1230                writeParameter(
1231                        sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
1232            }
1233    
1234            if (closure == null) return;
1235    
1236            for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
1237                Type type;
1238                if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
1239                    Type sharedVarType = getSharedVarType(variableDescriptor);
1240                    if (sharedVarType == null) {
1241                        sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
1242                    }
1243                    type = sharedVarType;
1244                }
1245                else if (isLocalFunction(variableDescriptor)) {
1246                    //noinspection CastConflictsWithInstanceof
1247                    type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
1248                }
1249                else {
1250                    type = null;
1251                }
1252    
1253                if (type != null) {
1254                    closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
1255                    writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
1256                }
1257            }
1258    
1259            // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
1260            // because such classes are not accessible from the outside world
1261            if (classBuilderMode.generateBodies) {
1262                ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
1263                if (superCall == null) return;
1264                writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
1265            }
1266        }
1267    
1268        private void writeSuperConstructorCallParameters(
1269                @NotNull JvmSignatureWriter sw,
1270                @NotNull ConstructorDescriptor descriptor,
1271                @NotNull ResolvedCall<ConstructorDescriptor> superCall,
1272                boolean hasOuter
1273        ) {
1274            ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor());
1275            List<ResolvedValueArgument> valueArguments = superCall.getValueArgumentsByIndex();
1276            assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor;
1277    
1278            List<JvmMethodParameterSignature> parameters = mapSignatureSkipGeneric(superDescriptor).getValueParameters();
1279    
1280            int params = parameters.size();
1281            int args = valueArguments.size();
1282    
1283            // Mapped parameters should consist of captured values plus all of valueArguments
1284            assert params >= args :
1285                    String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", params, args, descriptor);
1286    
1287            // Include all captured values, i.e. those parameters for which there are no resolved value arguments
1288            for (int i = 0; i < params - args; i++) {
1289                JvmMethodParameterSignature parameter = parameters.get(i);
1290                JvmMethodParameterKind kind = parameter.getKind();
1291                if (kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) continue;
1292                if (hasOuter && kind == JvmMethodParameterKind.OUTER) continue;
1293    
1294                writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1295            }
1296    
1297            if (isAnonymousObject(descriptor.getContainingDeclaration())) {
1298                // For anonymous objects, also add all real non-default value arguments passed to the super constructor
1299                for (int i = 0; i < args; i++) {
1300                    ResolvedValueArgument valueArgument = valueArguments.get(i);
1301                    JvmMethodParameterSignature parameter = parameters.get(params - args + i);
1302                    if (!(valueArgument instanceof DefaultValueArgument)) {
1303                        writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1304                    }
1305                }
1306            }
1307        }
1308    
1309        @Nullable
1310        private ResolvedCall<ConstructorDescriptor> findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) {
1311            ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
1312            while (true) {
1313                ResolvedCall<ConstructorDescriptor> next = getDelegationConstructorCall(bindingContext, descriptor);
1314                if (next == null) return null;
1315                descriptor = next.getResultingDescriptor();
1316                if (descriptor.getContainingDeclaration() != classDescriptor) return next;
1317            }
1318        }
1319    
1320        @NotNull
1321        public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
1322            JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
1323    
1324            sw.writeParametersStart();
1325    
1326            for (ScriptDescriptor importedScript : importedScripts) {
1327                writeParameter(sw, importedScript.getDefaultType(), /* callableDescriptor = */ null);
1328            }
1329    
1330            for (ValueParameterDescriptor valueParameter : script.getUnsubstitutedPrimaryConstructor().getValueParameters()) {
1331                writeParameter(sw, valueParameter.getType(), /* callableDescriptor = */ null);
1332            }
1333    
1334            writeVoidReturn(sw);
1335    
1336            return sw.makeJvmMethodSignature("<init>");
1337        }
1338    
1339        public Type getSharedVarType(DeclarationDescriptor descriptor) {
1340            if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
1341                return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
1342            }
1343            else if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
1344                ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1345                assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
1346                return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
1347            }
1348            else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
1349                return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
1350            }
1351            return null;
1352        }
1353    }