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