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