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