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