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