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