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