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