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