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