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