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