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