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