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