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