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