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 org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024    import org.jetbrains.kotlin.builtins.PrimitiveType;
025    import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor;
026    import org.jetbrains.kotlin.codegen.*;
027    import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
028    import org.jetbrains.kotlin.codegen.binding.MutableClosure;
029    import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor;
030    import org.jetbrains.kotlin.codegen.context.CodegenContext;
031    import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
032    import org.jetbrains.kotlin.descriptors.*;
033    import org.jetbrains.kotlin.descriptors.annotations.Annotated;
034    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
035    import org.jetbrains.kotlin.load.java.JvmAbi;
036    import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
037    import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
038    import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
039    import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
040    import org.jetbrains.kotlin.name.*;
041    import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
042    import org.jetbrains.kotlin.psi.JetExpression;
043    import org.jetbrains.kotlin.psi.JetFile;
044    import org.jetbrains.kotlin.psi.JetFunctionLiteral;
045    import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression;
046    import org.jetbrains.kotlin.resolve.BindingContext;
047    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
048    import org.jetbrains.kotlin.resolve.DescriptorUtils;
049    import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
050    import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
051    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
052    import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
053    import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
054    import org.jetbrains.kotlin.resolve.constants.StringValue;
055    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
056    import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
057    import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
058    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
059    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
060    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
061    import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
062    import org.jetbrains.kotlin.types.*;
063    import org.jetbrains.kotlin.types.expressions.OperatorConventions;
064    import org.jetbrains.org.objectweb.asm.Type;
065    import org.jetbrains.org.objectweb.asm.commons.Method;
066    
067    import java.io.File;
068    import java.util.ArrayList;
069    import java.util.List;
070    import java.util.Map;
071    
072    import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnit;
073    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
074    import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
075    import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
076    import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
077    import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
078    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
079    import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
080    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
081    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
082    
083    public class JetTypeMapper {
084        private final BindingContext bindingContext;
085        private final ClassBuilderMode classBuilderMode;
086    
087        public JetTypeMapper(@NotNull BindingContext bindingContext, @NotNull ClassBuilderMode classBuilderMode) {
088            this.bindingContext = bindingContext;
089            this.classBuilderMode = classBuilderMode;
090        }
091    
092        @NotNull
093        public BindingContext getBindingContext() {
094            return bindingContext;
095        }
096    
097        private enum JetTypeMapperMode {
098            /**
099             * foo.Bar is mapped to Lfoo/Bar;
100             */
101            IMPL,
102            /**
103             * kotlin.Int is mapped to I
104             */
105            VALUE,
106            /**
107             * kotlin.Int is mapped to Ljava/lang/Integer;
108             */
109            TYPE_PARAMETER,
110            /**
111             * kotlin.Int is mapped to Ljava/lang/Integer;
112             * No projections allowed in immediate arguments
113             */
114            SUPER_TYPE,
115            /**
116             * kotlin.reflect.KClass mapped to java.lang.Class
117             * Other types mapped as VALUE
118             */
119            VALUE_FOR_ANNOTATION,
120            /**
121             * kotlin.reflect.KClass mapped to java.lang.Class
122             * Other types mapped as TYPE_PARAMETER
123             */
124            TYPE_PARAMETER_FOR_ANNOTATION;
125    
126            boolean isForAnnotation() {
127                return this == VALUE_FOR_ANNOTATION || this == TYPE_PARAMETER_FOR_ANNOTATION;
128            }
129        }
130    
131        @NotNull
132        public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean isInsideModule) {
133            if (isLocalFunction(descriptor)) {
134                return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
135            }
136    
137            DeclarationDescriptor container = descriptor.getContainingDeclaration();
138            if (container instanceof PackageFragmentDescriptor) {
139                boolean effectiveInsideModule = isInsideModule && !NativeDeclarationsPackage.hasNativeAnnotation(descriptor);
140                return Type.getObjectType(internalNameForPackage(
141                        (PackageFragmentDescriptor) container,
142                        (CallableMemberDescriptor) descriptor,
143                        effectiveInsideModule
144                ));
145            }
146            else if (container instanceof ClassDescriptor) {
147                return mapClass((ClassDescriptor) container);
148            }
149            else if (container instanceof ScriptDescriptor) {
150                return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container);
151            }
152            else {
153                throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
154            }
155        }
156    
157        @NotNull
158        private static String internalNameForPackage(
159                @NotNull PackageFragmentDescriptor packageFragment,
160                @NotNull CallableMemberDescriptor descriptor,
161                boolean insideModule
162        ) {
163            if (insideModule) {
164                JetFile file = DescriptorToSourceUtils.getContainingFile(descriptor);
165                if (file != null) {
166                    return PackagePartClassUtils.getPackagePartInternalName(file);
167                }
168    
169                CallableMemberDescriptor directMember = getDirectMember(descriptor);
170    
171                if (directMember instanceof DeserializedCallableMemberDescriptor) {
172                    FqName packagePartFqName = PackagePartClassUtils.getPackagePartFqName((DeserializedCallableMemberDescriptor) directMember);
173                    return internalNameByFqNameWithoutInnerClasses(packagePartFqName);
174                }
175            }
176    
177            return PackageClassUtils.getPackageClassInternalName(packageFragment.getFqName());
178        }
179    
180        @NotNull
181        public Type mapReturnType(@NotNull CallableDescriptor descriptor) {
182            return mapReturnType(descriptor, null);
183        }
184    
185        @NotNull
186        private Type mapReturnType(@NotNull CallableDescriptor descriptor, @Nullable BothSignatureWriter sw) {
187            JetType returnType = descriptor.getReturnType();
188            assert returnType != null : "Function has no return type: " + descriptor;
189    
190            if (descriptor instanceof ConstructorDescriptor) {
191                return Type.VOID_TYPE;
192            }
193    
194            if (isUnit(returnType) && !TypeUtils.isNullableType(returnType) && !(descriptor instanceof PropertyGetterDescriptor)) {
195                if (sw != null) {
196                    sw.writeAsmType(Type.VOID_TYPE);
197                }
198                return Type.VOID_TYPE;
199            }
200            else if (descriptor instanceof FunctionDescriptor && forceBoxedReturnType((FunctionDescriptor) descriptor)) {
201                // TYPE_PARAMETER is a hack to automatically box the return type
202                //noinspection ConstantConditions
203                return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.TYPE_PARAMETER);
204            }
205            else if (DescriptorUtils.isAnnotationClass(descriptor.getContainingDeclaration())) {
206                //noinspection ConstantConditions
207                return mapType(descriptor.getReturnType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
208            }
209            else {
210                return mapType(returnType, sw, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE);
211            }
212        }
213    
214        @NotNull
215        private Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode mode) {
216            return mapType(jetType, null, mode);
217        }
218    
219        @NotNull
220        public Type mapSupertype(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
221            return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
222        }
223    
224        @NotNull
225        public Type mapTypeParameter(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
226            return mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
227        }
228    
229        @NotNull
230        public Type mapClass(@NotNull ClassifierDescriptor classifier) {
231            return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
232        }
233    
234        @NotNull
235        public Type mapType(@NotNull JetType jetType) {
236            return mapType(jetType, null, JetTypeMapperMode.VALUE);
237        }
238    
239        @NotNull
240        public Type mapType(@NotNull CallableDescriptor descriptor) {
241            //noinspection ConstantConditions
242            return mapType(descriptor.getReturnType());
243        }
244    
245        @NotNull
246        public JvmMethodSignature mapAnnotationParameterSignature(@NotNull PropertyDescriptor descriptor) {
247            BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
248            sw.writeReturnType();
249            mapType(descriptor.getType(), sw, JetTypeMapperMode.VALUE_FOR_ANNOTATION);
250            sw.writeReturnTypeEnd();
251            return sw.makeJvmMethodSignature(descriptor.getName().asString());
252        }
253    
254        @NotNull
255        public Type mapType(@NotNull ClassifierDescriptor descriptor) {
256            return mapType(descriptor.getDefaultType());
257        }
258    
259        @NotNull
260        private Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
261            return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT);
262        }
263    
264        @NotNull
265        private Type mapType(
266                @NotNull JetType jetType,
267                @Nullable BothSignatureWriter signatureVisitor,
268                @NotNull JetTypeMapperMode kind,
269                @NotNull Variance howThisTypeIsUsed
270        ) {
271            Type known = mapBuiltinType(jetType);
272    
273            boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
274            if (known != null) {
275                if (kind == JetTypeMapperMode.VALUE || kind == JetTypeMapperMode.VALUE_FOR_ANNOTATION) {
276                    return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
277                }
278                else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE ||
279                         kind == JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION) {
280                    return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, projectionsAllowed);
281                }
282                else if (kind == JetTypeMapperMode.IMPL) {
283                    // TODO: enable and fix tests
284                    //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
285                    return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
286                }
287                else {
288                    throw new IllegalStateException("unknown kind: " + kind);
289                }
290            }
291    
292            TypeConstructor constructor = jetType.getConstructor();
293            DeclarationDescriptor descriptor = constructor.getDeclarationDescriptor();
294            if (constructor instanceof IntersectionTypeConstructor) {
295                jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
296            }
297    
298            if (descriptor == null) {
299                throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
300            }
301    
302            if (ErrorUtils.isError(descriptor)) {
303                if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
304                    throw new IllegalStateException(generateErrorMessageForErrorType(jetType, descriptor));
305                }
306                Type asmType = Type.getObjectType("error/NonExistentClass");
307                if (signatureVisitor != null) {
308                    signatureVisitor.writeAsmType(asmType);
309                }
310                return asmType;
311            }
312    
313            if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.isArray(jetType)) {
314                if (jetType.getArguments().size() != 1) {
315                    throw new UnsupportedOperationException("arrays must have one type argument");
316                }
317                TypeProjection memberProjection = jetType.getArguments().get(0);
318                JetType memberType = memberProjection.getType();
319    
320                Type arrayElementType;
321                if (memberProjection.getProjectionKind() == Variance.IN_VARIANCE) {
322                    arrayElementType = AsmTypes.OBJECT_TYPE;
323                    if (signatureVisitor != null) {
324                        signatureVisitor.writeArrayType();
325                        signatureVisitor.writeAsmType(arrayElementType);
326                        signatureVisitor.writeArrayEnd();
327                    }
328                }
329                else {
330                    arrayElementType = boxType(mapType(memberType, kind));
331                    if (signatureVisitor != null) {
332                        signatureVisitor.writeArrayType();
333                        JetTypeMapperMode newMode = kind.isForAnnotation() ?
334                                                    JetTypeMapperMode.TYPE_PARAMETER_FOR_ANNOTATION :
335                                                    JetTypeMapperMode.TYPE_PARAMETER;
336                        mapType(memberType, signatureVisitor, newMode, memberProjection.getProjectionKind());
337                        signatureVisitor.writeArrayEnd();
338                    }
339                }
340    
341                return Type.getType("[" + arrayElementType.getDescriptor());
342            }
343    
344            if (descriptor instanceof ClassDescriptor) {
345                Type asmType = kind.isForAnnotation() && KotlinBuiltIns.isKClass((ClassDescriptor) descriptor) ?
346                               AsmTypes.JAVA_CLASS_TYPE :
347                               computeAsmType((ClassDescriptor) descriptor.getOriginal());
348                writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
349                return asmType;
350            }
351    
352            if (descriptor instanceof TypeParameterDescriptor) {
353                TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
354                Type type = mapType(typeParameterDescriptor.getUpperBounds().iterator().next(), kind);
355                if (signatureVisitor != null) {
356                    signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
357                }
358                return type;
359            }
360    
361            throw new UnsupportedOperationException("Unknown type " + jetType);
362        }
363    
364        @Nullable
365        private static Type mapBuiltinType(@NotNull JetType type) {
366            DeclarationDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
367            if (!(descriptor instanceof ClassDescriptor)) return null;
368    
369            FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
370    
371            PrimitiveType primitiveType = KotlinBuiltIns.getPrimitiveTypeByFqName(fqName);
372            if (primitiveType != null) {
373                Type asmType = Type.getType(JvmPrimitiveType.get(primitiveType).getDesc());
374                return TypeUtils.isNullableType(type) ? boxType(asmType) : asmType;
375            }
376    
377            PrimitiveType arrayElementType = KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(fqName);
378            if (arrayElementType != null) {
379                return Type.getType("[" + JvmPrimitiveType.get(arrayElementType).getDesc());
380            }
381    
382            ClassId classId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName);
383            if (classId != null) {
384                return Type.getObjectType(JvmClassName.byClassId(classId).getInternalName());
385            }
386    
387            return null;
388        }
389    
390        @NotNull
391        private Type computeAsmType(@NotNull ClassDescriptor klass) {
392            Type alreadyComputedType = bindingContext.get(ASM_TYPE, klass);
393            if (alreadyComputedType != null) {
394                return alreadyComputedType;
395            }
396    
397            Type asmType = Type.getObjectType(computeAsmTypeImpl(klass));
398            assert PsiCodegenPredictor.checkPredictedNameFromPsi(klass, asmType);
399            return asmType;
400        }
401    
402        @NotNull
403        private String computeAsmTypeImpl(@NotNull ClassDescriptor klass) {
404            DeclarationDescriptor container = klass.getContainingDeclaration();
405    
406            String name = SpecialNames.safeIdentifier(klass.getName()).getIdentifier();
407            if (container instanceof PackageFragmentDescriptor) {
408                FqName fqName = ((PackageFragmentDescriptor) container).getFqName();
409                return fqName.isRoot() ? name : fqName.asString().replace('.', '/') + '/' + name;
410            }
411    
412            if (container instanceof ScriptDescriptor) {
413                return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container).getInternalName() + "$" + name;
414            }
415    
416            assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass;
417    
418            String containerInternalName = computeAsmTypeImpl((ClassDescriptor) container);
419            return klass.getKind() == ClassKind.ENUM_ENTRY ? containerInternalName : containerInternalName + "$" + name;
420        }
421    
422        @NotNull
423        public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
424            return Type.getObjectType(mapType(descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
425        }
426    
427        @NotNull
428        private static String generateErrorMessageForErrorType(@NotNull JetType type, @NotNull DeclarationDescriptor descriptor) {
429            PsiElement declarationElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
430    
431            if (declarationElement == null) {
432                return String.format(
433                        "Error type encountered: %s (%s). " +
434                        "One of the possible reasons may be that this type is not directly accessible from this module. " +
435                        "To workaround this error, try adding an explicit dependency on the module or library which contains this type " +
436                        "to the classpath",
437                        type,
438                        type.getClass().getSimpleName()
439                );
440            }
441    
442            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
443            PsiElement parentDeclarationElement =
444                    containingDeclaration != null ? DescriptorToSourceUtils.descriptorToDeclaration(containingDeclaration) : null;
445    
446            return String.format(
447                    "Error type encountered: %s (%s). Descriptor: %s. For declaration %s:%s in %s:%s",
448                    type,
449                    type.getClass().getSimpleName(),
450                    descriptor,
451                    declarationElement,
452                    declarationElement.getText(),
453                    parentDeclarationElement,
454                    parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"
455            );
456        }
457    
458        private void writeGenericType(
459                BothSignatureWriter signatureVisitor,
460                Type asmType,
461                JetType jetType,
462                Variance howThisTypeIsUsed,
463                boolean projectionsAllowed
464        ) {
465            if (signatureVisitor != null) {
466                signatureVisitor.writeClassBegin(asmType);
467    
468                List<TypeProjection> arguments = jetType.getArguments();
469                for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
470                    TypeProjection argument = arguments.get(parameter.getIndex());
471    
472                    if (projectionsAllowed && argument.isStarProjection()) {
473                        signatureVisitor.writeUnboundedWildcard();
474                    }
475                    else {
476                        Variance projectionKind = projectionsAllowed
477                                                  ? getEffectiveVariance(
478                                parameter.getVariance(),
479                                argument.getProjectionKind(),
480                                howThisTypeIsUsed
481                        )
482                                                  : Variance.INVARIANT;
483                        signatureVisitor.writeTypeArgument(projectionKind);
484    
485                        mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
486                        signatureVisitor.writeTypeArgumentEnd();
487                    }
488                }
489                signatureVisitor.writeClassEnd();
490            }
491        }
492    
493        private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
494            // Return type must not contain wildcards
495            if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
496    
497            if (parameterVariance == Variance.INVARIANT) {
498                return projectionKind;
499            }
500            if (projectionKind == Variance.INVARIANT) {
501                return parameterVariance;
502            }
503            if (parameterVariance == projectionKind) {
504                return parameterVariance;
505            }
506    
507            // In<out X> = In<*>
508            // Out<in X> = Out<*>
509            return Variance.OUT_VARIANCE;
510        }
511    
512        private Type mapKnownAsmType(
513                JetType jetType,
514                Type asmType,
515                @Nullable BothSignatureWriter signatureVisitor,
516                @NotNull Variance howThisTypeIsUsed
517        ) {
518            return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, true);
519        }
520    
521        private Type mapKnownAsmType(
522                JetType jetType,
523                Type asmType,
524                @Nullable BothSignatureWriter signatureVisitor,
525                @NotNull Variance howThisTypeIsUsed,
526                boolean allowProjections
527        ) {
528            if (signatureVisitor != null) {
529                if (jetType.getArguments().isEmpty()) {
530                    signatureVisitor.writeAsmType(asmType);
531                }
532                else {
533                    writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
534                }
535            }
536            return asmType;
537        }
538    
539        @NotNull
540        public CallableMethod mapToCallableMethod(
541                @NotNull FunctionDescriptor descriptor,
542                boolean superCall,
543                @NotNull CodegenContext<?> context
544        ) {
545            DeclarationDescriptor functionParent = descriptor.getOriginal().getContainingDeclaration();
546    
547            FunctionDescriptor functionDescriptor = unwrapFakeOverride(descriptor.getOriginal());
548    
549            JvmMethodSignature signature;
550            Type owner;
551            Type ownerForDefaultImpl;
552            Type ownerForDefaultParam;
553            int invokeOpcode;
554            Type thisClass;
555    
556            if (functionParent instanceof ClassDescriptor) {
557                FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
558    
559                ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
560                ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
561    
562                boolean originalIsInterface = isInterface(declarationOwner);
563                boolean currentIsInterface = isInterface(currentOwner);
564    
565                boolean isInterface = currentIsInterface && originalIsInterface;
566    
567                ClassDescriptor ownerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
568                ownerForDefaultParam = mapClass(ownerForDefault);
569                ownerForDefaultImpl = isInterface(ownerForDefault) ? mapTraitImpl(ownerForDefault) : ownerForDefaultParam;
570    
571                if (isInterface && superCall) {
572                    thisClass = mapClass(currentOwner);
573                    if (declarationOwner instanceof JavaClassDescriptor) {
574                        invokeOpcode = INVOKESPECIAL;
575                        signature = mapSignature(functionDescriptor);
576                        owner = thisClass;
577                    }
578                    else {
579                        invokeOpcode = INVOKESTATIC;
580                        signature = mapSignature(functionDescriptor, OwnerKind.TRAIT_IMPL);
581                        owner = mapTraitImpl(currentOwner);
582                    }
583                }
584                else {
585                    if (isStaticDeclaration(functionDescriptor) ||
586                        isAccessor(functionDescriptor) ||
587                        AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
588                        invokeOpcode = INVOKESTATIC;
589                    }
590                    else if (isInterface) {
591                        invokeOpcode = INVOKEINTERFACE;
592                    }
593                    else {
594                        boolean isPrivateFunInvocation = Visibilities.isPrivate(functionDescriptor.getVisibility());
595                        invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
596                    }
597    
598                    signature = mapSignature(functionDescriptor.getOriginal());
599    
600                    ClassDescriptor receiver = (currentIsInterface && !originalIsInterface) || currentOwner instanceof FunctionClassDescriptor
601                                               ? declarationOwner
602                                               : currentOwner;
603                    owner = mapClass(receiver);
604                    thisClass = owner;
605                }
606            }
607            else {
608                signature = mapSignature(functionDescriptor.getOriginal());
609                owner = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context, getOutDirectory()));
610                ownerForDefaultParam = owner;
611                ownerForDefaultImpl = owner;
612                if (functionParent instanceof PackageFragmentDescriptor) {
613                    invokeOpcode = INVOKESTATIC;
614                    thisClass = null;
615                }
616                else if (functionDescriptor instanceof ConstructorDescriptor) {
617                    invokeOpcode = INVOKESPECIAL;
618                    thisClass = null;
619                }
620                else {
621                    invokeOpcode = INVOKEVIRTUAL;
622                    thisClass = owner;
623                }
624            }
625    
626            Type calleeType = isLocalFunction(functionDescriptor) ? owner : null;
627    
628            Type receiverParameterType;
629            ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getExtensionReceiverParameter();
630            if (receiverParameter != null) {
631                receiverParameterType = mapType(receiverParameter.getType());
632            }
633            else {
634                receiverParameterType = null;
635            }
636            return new CallableMethod(
637                    owner, ownerForDefaultImpl, ownerForDefaultParam, signature, invokeOpcode,
638                    thisClass, receiverParameterType, calleeType);
639        }
640    
641        public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
642            return descriptor instanceof AccessorForCallableDescriptor<?>;
643        }
644    
645        @NotNull
646        private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
647            if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
648                return function;
649            }
650            return findBaseDeclaration(function);
651        }
652    
653        @NotNull
654        private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
655            if (function.getOverriddenDescriptors().isEmpty()) {
656                return function;
657            }
658            else {
659                // TODO: prefer class to interface
660                return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
661            }
662        }
663    
664        @NotNull
665        private String mapFunctionName(@NotNull FunctionDescriptor descriptor) {
666            String platformName = getPlatformName(descriptor);
667            if (platformName != null) return platformName;
668    
669            if (descriptor instanceof PropertyAccessorDescriptor) {
670                PropertyDescriptor property = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
671                if (isAnnotationClass(property.getContainingDeclaration())) {
672                    return property.getName().asString();
673                }
674    
675                boolean isAccessor = property instanceof AccessorForPropertyDescriptor;
676                Name propertyName = isAccessor
677                                    ? Name.identifier(((AccessorForPropertyDescriptor) property).getIndexedAccessorSuffix())
678                                    : property.getName();
679    
680                String accessorName = descriptor instanceof PropertyGetterDescriptor
681                                      ? PropertyCodegen.getterName(propertyName)
682                                      : PropertyCodegen.setterName(propertyName);
683    
684                return isAccessor ? "access$" + accessorName : accessorName;
685            }
686            else if (isFunctionLiteral(descriptor)) {
687                PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
688                if (element instanceof JetFunctionLiteral) {
689                    PsiElement expression = element.getParent();
690                    if (expression instanceof JetFunctionLiteralExpression) {
691                        SamType samType = bindingContext.get(SAM_VALUE, (JetExpression) expression);
692                        if (samType != null) {
693                            return samType.getAbstractMethod().getName().asString();
694                        }
695                    }
696                }
697    
698                return OperatorConventions.INVOKE.asString();
699            }
700            else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
701                return OperatorConventions.INVOKE.asString();
702            }
703            else {
704                return descriptor.getName().asString();
705            }
706        }
707    
708        @Nullable
709        private static String getPlatformName(@NotNull Annotated descriptor) {
710            AnnotationDescriptor platformNameAnnotation = descriptor.getAnnotations().findAnnotation(new FqName("kotlin.platform.platformName"));
711            if (platformNameAnnotation == null) return null;
712    
713            Map<ValueParameterDescriptor, CompileTimeConstant<?>> arguments = platformNameAnnotation.getAllValueArguments();
714            if (arguments.isEmpty()) return null;
715    
716            CompileTimeConstant<?> name = arguments.values().iterator().next();
717            if (!(name instanceof StringValue)) return null;
718    
719            return ((StringValue) name).getValue();
720        }
721    
722        @NotNull
723        public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor descriptor) {
724            return mapSignature(descriptor, OwnerKind.IMPLEMENTATION);
725        }
726    
727        @NotNull
728        public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
729            if (f instanceof ConstructorDescriptor) {
730                return mapSignature(f, kind, f.getOriginal().getValueParameters());
731            }
732            return mapSignature(f, kind, f.getValueParameters());
733        }
734    
735        @NotNull
736        public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind,
737                List<ValueParameterDescriptor> valueParameters) {
738            BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
739    
740            if (f instanceof ConstructorDescriptor) {
741                sw.writeParametersStart();
742                writeAdditionalConstructorParameters((ConstructorDescriptor) f, sw);
743    
744                for (ValueParameterDescriptor parameter : valueParameters) {
745                    writeParameter(sw, parameter.getType());
746                }
747    
748                writeVoidReturn(sw);
749            }
750            else {
751                writeFormalTypeParameters(getDirectMember(f).getTypeParameters(), sw);
752    
753                sw.writeParametersStart();
754                writeThisIfNeeded(f, kind, sw);
755    
756                ReceiverParameterDescriptor receiverParameter = f.getExtensionReceiverParameter();
757                if (receiverParameter != null) {
758                    writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.getType());
759                }
760    
761                for (ValueParameterDescriptor parameter : valueParameters) {
762                    writeParameter(sw, parameter.getType());
763                }
764    
765                sw.writeReturnType();
766                mapReturnType(f, sw);
767                sw.writeReturnTypeEnd();
768            }
769    
770            return sw.makeJvmMethodSignature(mapFunctionName(f));
771        }
772    
773        @NotNull
774        public static String getDefaultDescriptor(@NotNull Method method, @Nullable String dispatchReceiverDescriptor, boolean isExtension) {
775            String descriptor = method.getDescriptor();
776            int argumentsCount = Type.getArgumentTypes(descriptor).length;
777            if (isExtension) {
778                argumentsCount--;
779            }
780            int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
781            String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
782            if (isConstructor(method)) {
783                additionalArgs += DEFAULT_CONSTRUCTOR_MARKER.getDescriptor();
784            }
785            String result = descriptor.replace(")", additionalArgs + ")");
786            if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
787                return result.replace("(", "(" + dispatchReceiverDescriptor);
788            }
789            return result;
790        }
791    
792        public ClassBuilderMode getClassBuilderMode() {
793            return classBuilderMode;
794        }
795    
796        private static boolean isConstructor(@NotNull Method method) {
797            return "<init>".equals(method.getName());
798        }
799    
800        @NotNull
801        public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind, @NotNull CodegenContext<?> context) {
802            Method jvmSignature = mapSignature(functionDescriptor, kind).getAsmMethod();
803            Type ownerType = mapOwner(functionDescriptor, isCallInsideSameModuleAsDeclared(functionDescriptor, context, getOutDirectory()));
804            boolean isConstructor = isConstructor(jvmSignature);
805            String descriptor = getDefaultDescriptor(jvmSignature,
806                                                     isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(),
807                                                     functionDescriptor.getExtensionReceiverParameter() != null);
808    
809            return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
810        }
811    
812        /**
813         * @return true iff a given function descriptor should be compiled to a method with boxed return type regardless of whether return type
814         * of that descriptor is nullable or not. This happens when a function returning a value of a primitive type overrides another function
815         * 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
816         * this class from Java since javac issues errors when loading the class (incompatible return types)
817         */
818        private static boolean forceBoxedReturnType(@NotNull FunctionDescriptor descriptor) {
819            //noinspection ConstantConditions
820            if (!KotlinBuiltIns.isPrimitiveType(descriptor.getReturnType())) return false;
821    
822            for (FunctionDescriptor overridden : getAllOverriddenDescriptors(descriptor)) {
823                //noinspection ConstantConditions
824                if (!KotlinBuiltIns.isPrimitiveType(overridden.getOriginal().getReturnType())) return true;
825            }
826    
827            return false;
828        }
829    
830        private static void writeVoidReturn(@NotNull BothSignatureWriter sw) {
831            sw.writeReturnType();
832            sw.writeAsmType(Type.VOID_TYPE);
833            sw.writeReturnTypeEnd();
834        }
835    
836        @Nullable
837        public String mapFieldSignature(@NotNull JetType backingFieldType) {
838            BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
839            mapType(backingFieldType, sw, JetTypeMapperMode.VALUE);
840            return sw.makeJavaGenericSignature();
841        }
842    
843        private void writeThisIfNeeded(
844                @NotNull CallableMemberDescriptor descriptor,
845                @NotNull OwnerKind kind,
846                @NotNull BothSignatureWriter sw
847        ) {
848            ClassDescriptor thisType;
849            if (kind == OwnerKind.TRAIT_IMPL) {
850                thisType = getTraitImplThisParameterClass((ClassDescriptor) descriptor.getContainingDeclaration());
851            }
852            else if (isAccessor(descriptor) && descriptor.getDispatchReceiverParameter() != null) {
853                thisType = (ClassDescriptor) descriptor.getContainingDeclaration();
854            }
855            else return;
856    
857            writeParameter(sw, JvmMethodParameterKind.THIS, thisType.getDefaultType());
858        }
859    
860        @NotNull
861        private static ClassDescriptor getTraitImplThisParameterClass(@NotNull ClassDescriptor traitDescriptor) {
862            for (ClassDescriptor descriptor : DescriptorUtils.getSuperclassDescriptors(traitDescriptor)) {
863                if (descriptor.getKind() != ClassKind.INTERFACE) {
864                    return descriptor;
865                }
866            }
867            return traitDescriptor;
868        }
869    
870        public void writeFormalTypeParameters(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull BothSignatureWriter sw) {
871            for (TypeParameterDescriptor typeParameter : typeParameters) {
872                writeFormalTypeParameter(typeParameter, sw);
873            }
874        }
875    
876        private void writeFormalTypeParameter(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull BothSignatureWriter sw) {
877            if (classBuilderMode == ClassBuilderMode.LIGHT_CLASSES && typeParameterDescriptor.getName().isSpecial()) {
878                // If a type parameter has no name, the code below fails, but it should recover in case of light classes
879                return;
880            }
881    
882            sw.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
883    
884            classBound:
885            {
886                sw.writeClassBound();
887    
888                for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
889                    if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
890                        if (!isInterface(jetType)) {
891                            mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
892                            break classBound;
893                        }
894                    }
895                }
896    
897                // "extends Object" is optional according to ClassFileFormat-Java5.pdf
898                // but javac complaints to signature:
899                // <P:>Ljava/lang/Object;
900                // TODO: avoid writing java/lang/Object if interface list is not empty
901            }
902            sw.writeClassBoundEnd();
903    
904            for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
905                ClassifierDescriptor classifier = jetType.getConstructor().getDeclarationDescriptor();
906                if (classifier instanceof ClassDescriptor) {
907                    if (isInterface(jetType)) {
908                        sw.writeInterfaceBound();
909                        mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
910                        sw.writeInterfaceBoundEnd();
911                    }
912                }
913                else if (classifier instanceof TypeParameterDescriptor) {
914                    sw.writeInterfaceBound();
915                    mapType(jetType, sw, JetTypeMapperMode.TYPE_PARAMETER);
916                    sw.writeInterfaceBoundEnd();
917                }
918                else {
919                    throw new UnsupportedOperationException("Unknown classifier: " + classifier);
920                }
921            }
922        }
923    
924        private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JetType type) {
925            writeParameter(sw, JvmMethodParameterKind.VALUE, type);
926        }
927    
928        private void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull JetType type) {
929            sw.writeParameterType(kind);
930            mapType(type, sw, JetTypeMapperMode.VALUE);
931            sw.writeParameterTypeEnd();
932        }
933    
934        private static void writeParameter(@NotNull BothSignatureWriter sw, @NotNull JvmMethodParameterKind kind, @NotNull Type type) {
935            sw.writeParameterType(kind);
936            sw.writeAsmType(type);
937            sw.writeParameterTypeEnd();
938        }
939    
940        private void writeAdditionalConstructorParameters(@NotNull ConstructorDescriptor descriptor, @NotNull BothSignatureWriter sw) {
941            MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
942    
943            ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
944            if (captureThis != null) {
945                writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType());
946            }
947    
948            JetType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
949            if (captureReceiverType != null) {
950                writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType);
951            }
952    
953            ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
954            if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
955                writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, getBuiltIns(descriptor).getStringType());
956                writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, getBuiltIns(descriptor).getIntType());
957            }
958    
959            if (closure == null) return;
960    
961            for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
962                Type type;
963                if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
964                    Type sharedVarType = getSharedVarType(variableDescriptor);
965                    if (sharedVarType == null) {
966                        sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
967                    }
968                    type = sharedVarType;
969                }
970                else if (isLocalFunction(variableDescriptor)) {
971                    //noinspection CastConflictsWithInstanceof
972                    type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
973                }
974                else {
975                    type = null;
976                }
977    
978                if (type != null) {
979                    closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
980                    writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
981                }
982            }
983    
984            // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
985            // because such classes are not accessible from the outside world
986            if (classBuilderMode == ClassBuilderMode.FULL) {
987                ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
988                if (superCall == null) return;
989                writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
990            }
991        }
992    
993        private void writeSuperConstructorCallParameters(
994                @NotNull BothSignatureWriter sw,
995                @NotNull ConstructorDescriptor descriptor,
996                @NotNull ResolvedCall<ConstructorDescriptor> superCall,
997                boolean hasOuter
998        ) {
999            ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor());
1000            List<ResolvedValueArgument> valueArguments = superCall.getValueArgumentsByIndex();
1001            assert valueArguments != null : "Failed to arrange value arguments by index: " + superDescriptor;
1002    
1003            List<JvmMethodParameterSignature> parameters = mapSignature(superDescriptor).getValueParameters();
1004    
1005            int params = parameters.size();
1006            int args = valueArguments.size();
1007    
1008            // Mapped parameters should consist of captured values plus all of valueArguments
1009            assert params >= args :
1010                    String.format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", params, args, descriptor);
1011    
1012            // Include all captured values, i.e. those parameters for which there are no resolved value arguments
1013            for (int i = 0; i < params - args; i++) {
1014                JvmMethodParameterSignature parameter = parameters.get(i);
1015                JvmMethodParameterKind kind = parameter.getKind();
1016                if (kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) continue;
1017                if (hasOuter && kind == JvmMethodParameterKind.OUTER) continue;
1018    
1019                writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1020            }
1021    
1022            if (isAnonymousObject(descriptor.getContainingDeclaration())) {
1023                // For anonymous objects, also add all real non-default value arguments passed to the super constructor
1024                for (int i = 0; i < args; i++) {
1025                    ResolvedValueArgument valueArgument = valueArguments.get(i);
1026                    JvmMethodParameterSignature parameter = parameters.get(params - args + i);
1027                    if (!(valueArgument instanceof DefaultValueArgument)) {
1028                        writeParameter(sw, JvmMethodParameterKind.SUPER_CALL_PARAM, parameter.getAsmType());
1029                    }
1030                }
1031            }
1032        }
1033    
1034        @Nullable
1035        private ResolvedCall<ConstructorDescriptor> findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) {
1036            ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
1037            while (true) {
1038                ResolvedCall<ConstructorDescriptor> next = getDelegationConstructorCall(bindingContext, descriptor);
1039                if (next == null) return null;
1040                descriptor = next.getResultingDescriptor();
1041                if (descriptor.getContainingDeclaration() != classDescriptor) return next;
1042            }
1043        }
1044    
1045        @NotNull
1046        public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
1047            BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
1048    
1049            sw.writeParametersStart();
1050    
1051            for (ScriptDescriptor importedScript : importedScripts) {
1052                ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
1053                assert descriptor != null : "Script not found: " + importedScript;
1054                writeParameter(sw, descriptor.getDefaultType());
1055            }
1056    
1057            for (ValueParameterDescriptor valueParameter : script.getScriptCodeDescriptor().getValueParameters()) {
1058                writeParameter(sw, valueParameter.getType());
1059            }
1060    
1061            writeVoidReturn(sw);
1062    
1063            return sw.makeJvmMethodSignature("<init>");
1064        }
1065    
1066        @NotNull
1067        public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
1068            JvmMethodSignature method = mapSignature(descriptor);
1069            ClassDescriptor container = descriptor.getContainingDeclaration();
1070            Type owner = mapClass(container);
1071            if (owner.getSort() != Type.OBJECT) {
1072                throw new IllegalStateException("type must have been mapped to object: " + container.getDefaultType() + ", actual: " + owner);
1073            }
1074            return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
1075        }
1076    
1077        public Type getSharedVarType(DeclarationDescriptor descriptor) {
1078            if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
1079                return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
1080            }
1081            else if (descriptor instanceof PropertyDescriptor || descriptor instanceof FunctionDescriptor) {
1082                ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1083                assert receiverParameter != null : "Callable should have a receiver parameter: " + descriptor;
1084                return StackValue.sharedTypeForType(mapType(receiverParameter.getType()));
1085            }
1086            else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
1087                return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
1088            }
1089            return null;
1090        }
1091    
1092        // TODO Temporary hack until modules infrastructure is implemented. See JetTypeMapperWithOutDirectory for details
1093        @Nullable
1094        protected File getOutDirectory() {
1095            return null;
1096        }
1097    }