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