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