From 1b3b55408469da1a321e7b3ad18d1a9cfc4efc99 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 26 Mar 2023 00:30:38 -0700 Subject: [PATCH] SLC: force boxed return type when needed e.g., when overriding a function whose return type is not primitive ^KT-57579 Fixed --- .../components/KtFe10PsiTypeProvider.kt | 1 + .../fir/components/KtFirPsiTypeProvider.kt | 1 + .../analysis/api/types/KtTypeMappingMode.kt | 5 ++++ .../methods/SymbolLightAccessorMethod.kt | 13 ++++++++-- .../symbol/methods/SymbolLightSimpleMethod.kt | 25 ++++++++++++++++++- .../IntOverridesAny.fir.java | 4 +-- 6 files changed, 44 insertions(+), 5 deletions(-) diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt index 0e5cefd6e14..ec066d35979 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt @@ -62,6 +62,7 @@ internal class KtFe10PsiTypeProvider( KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS + KtTypeMappingMode.RETURN_TYPE_BOXED -> TypeMappingMode.RETURN_TYPE_BOXED KtTypeMappingMode.RETURN_TYPE -> typeMapper.typeContext.getOptimalModeForReturnType(type.fe10Type, isAnnotationMethod) KtTypeMappingMode.VALUE_PARAMETER -> diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt index f917f66115e..678d2fc6bee 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt @@ -76,6 +76,7 @@ internal class KtFirPsiTypeProvider( KtTypeMappingMode.GENERIC_ARGUMENT -> TypeMappingMode.GENERIC_ARGUMENT KtTypeMappingMode.SUPER_TYPE -> TypeMappingMode.SUPER_TYPE KtTypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS -> TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS + KtTypeMappingMode.RETURN_TYPE_BOXED -> TypeMappingMode.RETURN_TYPE_BOXED KtTypeMappingMode.RETURN_TYPE -> rootModuleSession.jvmTypeMapper.typeContext.getOptimalModeForReturnType(type.coneType, isAnnotationMethod) KtTypeMappingMode.VALUE_PARAMETER -> diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtTypeMappingMode.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtTypeMappingMode.kt index e2ad7d4f14b..755943a770c 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtTypeMappingMode.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/types/KtTypeMappingMode.kt @@ -33,6 +33,11 @@ public enum class KtTypeMappingMode { */ SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS, + /** + * When method return type should be boxed (e.g., kotlin.Int to Ljava/lang/Integer;) + */ + RETURN_TYPE_BOXED, + /** * Optimal mode to convert the return type of declarations if it's part of signature. */ diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt index d729edc2e77..b8ca0617505 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt @@ -238,10 +238,19 @@ internal class SymbolLightAccessorMethod private constructor( if (!isGetter) return@lazyPub PsiType.VOID containingPropertySymbolPointer.withSymbol(ktModule) { propertySymbol -> - propertySymbol.returnType.asPsiType( + val ktType = propertySymbol.returnType + + val forceBoxedReturnType = ktType.isPrimitive && + propertySymbol.getAllOverriddenSymbols().any { overriddenSymbol -> + !overriddenSymbol.returnType.isPrimitive + } + + val typeMappingMode = if (forceBoxedReturnType) KtTypeMappingMode.RETURN_TYPE_BOXED else KtTypeMappingMode.RETURN_TYPE + + ktType.asPsiType( this@SymbolLightAccessorMethod, allowErrorTypes = true, - KtTypeMappingMode.RETURN_TYPE, + typeMappingMode, containingClass.isAnnotationType, ) } ?: nonExistentType() diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt index 6751d20a5f8..571244d5879 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt @@ -11,6 +11,8 @@ import kotlinx.collections.immutable.mutate import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.annotations.hasAnnotation import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol +import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin @@ -177,6 +179,25 @@ internal class SymbolLightSimpleMethod( if (isTopLevel) false else withFunctionSymbol { it.isOverride } } + // Inspired by KotlinTypeMapper#forceBoxedReturnType + private fun forceBoxedReturnType(): Boolean { + return withFunctionSymbol { functionSymbol -> + val returnType = functionSymbol.returnType + // 'invoke' methods for lambdas, function literals, and callable references + // implicitly override generic 'invoke' from a corresponding base class. + if (functionSymbol.isBuiltinFunctionInvoke && returnType.isInlineClassType) + return@withFunctionSymbol true + + returnType.isPrimitive && + functionSymbol.getAllOverriddenSymbols().any { overriddenSymbol -> + !overriddenSymbol.returnType.isPrimitive + } + } + } + + private val KtType.isInlineClassType: Boolean + get() = ((this as? KtNonErrorClassType)?.classSymbol as? KtNamedClassOrObjectSymbol)?.isInline == true + private val KtType.isVoidType: Boolean get() = isUnit && nullabilityType != NullabilityType.Nullable private val _returnedType: PsiType by lazyPub { @@ -187,10 +208,12 @@ internal class SymbolLightSimpleMethod( functionSymbol.returnType.takeUnless { it.isVoidType } ?: return@withFunctionSymbol PsiType.VOID } + val typeMappingMode = if (forceBoxedReturnType()) KtTypeMappingMode.RETURN_TYPE_BOXED else KtTypeMappingMode.RETURN_TYPE + ktType.asPsiTypeElement( this@SymbolLightSimpleMethod, allowErrorTypes = true, - KtTypeMappingMode.RETURN_TYPE, + typeMappingMode, this@SymbolLightSimpleMethod.containingClass.isAnnotationType, )?.let { annotateByKtType(it.type, ktType, it, modifierList) diff --git a/compiler/testData/asJava/lightClasses/lightClassByFqName/nullabilityAnnotations/IntOverridesAny.fir.java b/compiler/testData/asJava/lightClasses/lightClassByFqName/nullabilityAnnotations/IntOverridesAny.fir.java index 357e781fdb5..e0a166d8bd8 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByFqName/nullabilityAnnotations/IntOverridesAny.fir.java +++ b/compiler/testData/asJava/lightClasses/lightClassByFqName/nullabilityAnnotations/IntOverridesAny.fir.java @@ -2,10 +2,10 @@ public final class C /* C*/ implements Tr { private final int v; @java.lang.Override() - public int foo();// foo() + public java.lang.Integer foo();// foo() @java.lang.Override() - public int getV();// getV() + public java.lang.Integer getV();// getV() public C();// .ctor() }