[FIR] Defer computation of enhanced return type when overridden has implicit return type
#KT-66048
This commit is contained in:
committed by
Space Team
parent
888cac6fc0
commit
885ba11d97
+103
-18
@@ -22,26 +22,35 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusIm
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirLiteralExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaTypeConversionMode
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaExternalAnnotation
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.java.declarations.buildJavaField
|
||||
import org.jetbrains.kotlin.fir.java.resolveIfJavaType
|
||||
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.DeferredCallableCopyReturnType
|
||||
import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.deferredCallableCopyReturnType
|
||||
import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
|
||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||
import org.jetbrains.kotlin.load.java.AnnotationQualifierApplicabilityType
|
||||
@@ -110,7 +119,7 @@ class FirSignatureEnhancement(
|
||||
emptyList()
|
||||
)
|
||||
|
||||
val newReturnTypeRef = enhanceReturnType(firElement, emptyList(), firElement.computeDefaultQualifiers(), predefinedInfo)
|
||||
val newReturnTypeRef = enhanceReturnType(firElement, firElement.computeDefaultQualifiers(), predefinedInfo)
|
||||
|
||||
return buildEnumEntryCopy(firElement) {
|
||||
symbol = FirEnumEntrySymbol(firElement.symbol.callableId)
|
||||
@@ -123,12 +132,13 @@ class FirSignatureEnhancement(
|
||||
is FirField -> {
|
||||
if (firElement.returnTypeRef !is FirJavaTypeRef) return original
|
||||
val newReturnTypeRef = enhanceReturnType(
|
||||
firElement, emptyList(), firElement.computeDefaultQualifiers(),
|
||||
firElement, firElement.computeDefaultQualifiers(),
|
||||
predefinedEnhancementInfo = null
|
||||
).let {
|
||||
val lowerBound = it.type.lowerBoundIfFlexible()
|
||||
if (lowerBound.isString && firElement.isStatic && firElement.hasConstantInitializer) {
|
||||
it.withReplacedConeType(it.type.withNullability(ConeNullability.NOT_NULL, session.typeContext))
|
||||
val coneTypeOrNull = it.coneTypeOrNull
|
||||
val lowerBound = coneTypeOrNull?.lowerBoundIfFlexible()
|
||||
if (lowerBound != null && lowerBound.isString && firElement.isStatic && firElement.hasConstantInitializer) {
|
||||
it.withReplacedConeType(coneTypeOrNull.withNullability(ConeNullability.NOT_NULL, session.typeContext))
|
||||
} else {
|
||||
it
|
||||
}
|
||||
@@ -260,10 +270,10 @@ class FirSignatureEnhancement(
|
||||
val newReceiverTypeRef = if (firMethod is FirSimpleFunction && hasReceiver) {
|
||||
enhanceReceiverType(firMethod, overriddenMembers, defaultQualifiers)
|
||||
} else null
|
||||
val newReturnTypeRef = if (firMethod is FirSimpleFunction) {
|
||||
val (newReturnTypeRef, deferredCalc) = if (firMethod is FirSimpleFunction) {
|
||||
enhanceReturnType(firMethod, overriddenMembers, defaultQualifiers, predefinedEnhancementInfo)
|
||||
} else {
|
||||
firMethod.returnTypeRef
|
||||
firMethod.returnTypeRef to null
|
||||
}
|
||||
|
||||
val enhancedValueParameterTypes = mutableListOf<FirResolvedTypeRef>()
|
||||
@@ -290,7 +300,7 @@ class FirSignatureEnhancement(
|
||||
val symbol = FirConstructorSymbol(methodId).also { functionSymbol = it }
|
||||
if (firMethod.isPrimary) {
|
||||
FirPrimaryConstructorBuilder().apply {
|
||||
returnTypeRef = newReturnTypeRef
|
||||
returnTypeRef = newReturnTypeRef!! // Constructors don't have overriddens, newReturnTypeRef is never null
|
||||
val resolvedStatus = firMethod.status as? FirResolvedDeclarationStatus
|
||||
status = if (resolvedStatus != null) {
|
||||
FirResolvedDeclarationStatusImpl(
|
||||
@@ -311,7 +321,7 @@ class FirSignatureEnhancement(
|
||||
}
|
||||
} else {
|
||||
FirConstructorBuilder().apply {
|
||||
returnTypeRef = newReturnTypeRef
|
||||
returnTypeRef = newReturnTypeRef!! // Constructors don't have overriddens, newReturnTypeRef is never null
|
||||
status = firMethod.status
|
||||
this.symbol = symbol
|
||||
dispatchReceiverType = firMethod.dispatchReceiverType
|
||||
@@ -364,9 +374,13 @@ class FirSignatureEnhancement(
|
||||
if (typeParameterSubstitutionMap.isNotEmpty()) {
|
||||
typeParameterSubstitutor = ConeSubstitutorByMap.create(typeParameterSubstitutionMap, session)
|
||||
}
|
||||
returnTypeRef = newReturnTypeRef.withReplacedConeType(
|
||||
typeParameterSubstitutor?.substituteOrNull(newReturnTypeRef.coneType)
|
||||
)
|
||||
returnTypeRef = if (typeParameterSubstitutor != null && newReturnTypeRef is FirResolvedTypeRef) {
|
||||
newReturnTypeRef.withReplacedConeType(
|
||||
typeParameterSubstitutor?.substituteOrNull(newReturnTypeRef.coneType)
|
||||
)
|
||||
} else {
|
||||
newReturnTypeRef ?: FirImplicitTypeRefImplWithoutSource
|
||||
}
|
||||
val substitutedReceiverTypeRef = newReceiverTypeRef?.withReplacedConeType(
|
||||
typeParameterSubstitutor?.substituteOrNull(newReceiverTypeRef.coneType)
|
||||
)
|
||||
@@ -386,7 +400,15 @@ class FirSignatureEnhancement(
|
||||
}
|
||||
|
||||
dispatchReceiverType = firMethod.dispatchReceiverType
|
||||
attributes = firMethod.attributes.copy()
|
||||
attributes = firMethod.attributes.copy().apply {
|
||||
if (deferredCalc != null) {
|
||||
deferredCallableCopyReturnType = if (typeParameterSubstitutor != null) {
|
||||
DelegatingDeferredReturnTypeWithSubstitution(deferredCalc, typeParameterSubstitutor!!)
|
||||
} else {
|
||||
deferredCalc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> errorWithAttachment("Unknown Java method to enhance: ${firMethod::class.java}") {
|
||||
@@ -631,12 +653,25 @@ class FirSignatureEnhancement(
|
||||
)
|
||||
}
|
||||
|
||||
private fun enhanceReturnType(
|
||||
owner: FirCallableDeclaration,
|
||||
defaultQualifiers: JavaTypeQualifiersByElementType?,
|
||||
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?,
|
||||
): FirResolvedTypeRef {
|
||||
return enhanceReturnType(owner, emptyList(), defaultQualifiers, predefinedEnhancementInfo).first!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Either returns a not-null [FirResolvedTypeRef] or a not-null [DeferredCallableCopyReturnType], never both.
|
||||
*
|
||||
* [DeferredCallableCopyReturnType] can only (but doesn't need to) be not-null when [overriddenMembers] is non-empty.
|
||||
*/
|
||||
private fun enhanceReturnType(
|
||||
owner: FirCallableDeclaration,
|
||||
overriddenMembers: List<FirCallableDeclaration>,
|
||||
defaultQualifiers: JavaTypeQualifiersByElementType?,
|
||||
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?
|
||||
): FirResolvedTypeRef {
|
||||
predefinedEnhancementInfo: PredefinedFunctionEnhancementInfo?,
|
||||
): Pair<FirResolvedTypeRef?, DeferredCallableCopyReturnType?> {
|
||||
val containerApplicabilityType = if (owner is FirJavaField) {
|
||||
AnnotationQualifierApplicabilityType.FIELD
|
||||
} else {
|
||||
@@ -650,6 +685,28 @@ class FirSignatureEnhancement(
|
||||
} else {
|
||||
this.owner.classKind == ClassKind.ANNOTATION_CLASS
|
||||
}
|
||||
|
||||
// If any overridden member has implicit return type, we need to defer the return type computation.
|
||||
if (overriddenMembers.any { it.returnTypeRef is FirImplicitTypeRef }) {
|
||||
val deferredReturnTypeCalculation = object : DeferredCallableCopyReturnType() {
|
||||
override fun computeReturnType(calc: CallableCopyTypeCalculator): ConeKotlinType {
|
||||
return owner.enhance(
|
||||
overriddenMembers,
|
||||
owner,
|
||||
isCovariant = true,
|
||||
defaultQualifiers,
|
||||
containerApplicabilityType,
|
||||
typeInSignature = TypeInSignature.ReturnPossiblyDeferred(calc),
|
||||
predefinedEnhancementInfo?.returnTypeInfo,
|
||||
forAnnotationMember = forAnnotationMember
|
||||
).type
|
||||
}
|
||||
|
||||
override fun toString(): String = "Deferred for Enhancement (Overriddens with Implicit Types)"
|
||||
}
|
||||
return null to deferredReturnTypeCalculation
|
||||
}
|
||||
|
||||
return owner.enhance(
|
||||
overriddenMembers,
|
||||
owner,
|
||||
@@ -659,16 +716,28 @@ class FirSignatureEnhancement(
|
||||
TypeInSignature.Return,
|
||||
predefinedEnhancementInfo?.returnTypeInfo,
|
||||
forAnnotationMember = forAnnotationMember
|
||||
)
|
||||
) to null
|
||||
}
|
||||
|
||||
private sealed class TypeInSignature {
|
||||
private abstract class TypeInSignature {
|
||||
abstract fun getTypeRef(member: FirCallableDeclaration): FirTypeRef
|
||||
|
||||
object Return : TypeInSignature() {
|
||||
override fun getTypeRef(member: FirCallableDeclaration): FirTypeRef = member.returnTypeRef
|
||||
}
|
||||
|
||||
class ReturnPossiblyDeferred(private val calc: CallableCopyTypeCalculator) : TypeInSignature() {
|
||||
override fun getTypeRef(member: FirCallableDeclaration): FirTypeRef {
|
||||
return if (member.isJava) {
|
||||
member.returnTypeRef
|
||||
} else {
|
||||
calc.computeReturnType(member) ?: buildErrorTypeRef {
|
||||
diagnostic = ConeSimpleDiagnostic("Could not resolve returnType for $member")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Receiver : TypeInSignature() {
|
||||
override fun getTypeRef(member: FirCallableDeclaration): FirTypeRef {
|
||||
if (member is FirSimpleFunction && member.isJava) {
|
||||
@@ -752,6 +821,22 @@ class FirSignatureEnhancement(
|
||||
toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack, mode)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates computation of return type to [deferredCalc] and substitutes the resulting type with [substitutor].
|
||||
*/
|
||||
private class DelegatingDeferredReturnTypeWithSubstitution(
|
||||
private val deferredCalc: DeferredCallableCopyReturnType,
|
||||
private val substitutor: ConeSubstitutor,
|
||||
) : DeferredCallableCopyReturnType() {
|
||||
override fun computeReturnType(calc: CallableCopyTypeCalculator): ConeKotlinType? {
|
||||
return deferredCalc.computeReturnType(calc)?.let(substitutor::substituteOrSelf)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "DelegatingDeferredReturnTypeWithSubstitution(deferredCalc=$deferredCalc, substitutor=$substitutor)"
|
||||
}
|
||||
}
|
||||
|
||||
private class EnhancementSignatureParts(
|
||||
private val session: FirSession,
|
||||
override val annotationTypeQualifierResolver: FirAnnotationTypeQualifierResolver,
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.canHaveDeferredReturnTypeCalculation
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
@@ -36,7 +37,7 @@ class ReturnTypeCalculatorForFullBodyResolve private constructor(
|
||||
override fun tryCalculateReturnTypeOrNull(declaration: FirCallableDeclaration): FirResolvedTypeRef? {
|
||||
val returnTypeRef = declaration.returnTypeRef
|
||||
if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef
|
||||
if (declaration.origin.fromSupertypes) {
|
||||
if (declaration.canHaveDeferredReturnTypeCalculation) {
|
||||
return CallableCopyTypeCalculator.Forced.computeReturnType(declaration)
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -5,13 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.canHaveDeferredReturnTypeCalculation
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.isCopyCreatedInScope
|
||||
import org.jetbrains.kotlin.fir.scopes.CallableCopyTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirDelegatingTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
@@ -59,7 +61,7 @@ class FirScopeWithCallableCopyReturnTypeUpdater(
|
||||
}
|
||||
|
||||
private fun updateReturnType(declaration: FirCallableDeclaration) {
|
||||
if (declaration.isCopyCreatedInScope) {
|
||||
if (declaration.canHaveDeferredReturnTypeCalculation) {
|
||||
callableCopyTypeCalculator.computeReturnType(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ open class ReturnTypeCalculatorWithJump(
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration.isCopyCreatedInScope) {
|
||||
if (declaration.canHaveDeferredReturnTypeCalculation) {
|
||||
val resolvedTypeRef = callableCopyTypeCalculator.computeReturnType(declaration)
|
||||
requireWithAttachment(
|
||||
resolvedTypeRef is FirResolvedTypeRef,
|
||||
|
||||
@@ -74,6 +74,7 @@ val FirCallableDeclaration.isSubstitutionOverride: Boolean get() = origin is Fir
|
||||
val FirCallableDeclaration.isSubstitutionOrIntersectionOverride: Boolean get() = isSubstitutionOverride || isIntersectionOverride
|
||||
val FirCallableDeclaration.isDelegated: Boolean get() = origin == FirDeclarationOrigin.Delegated
|
||||
val FirCallableDeclaration.isCopyCreatedInScope: Boolean get() = isSubstitutionOrIntersectionOverride || isDelegated
|
||||
val FirCallableDeclaration.canHaveDeferredReturnTypeCalculation: Boolean get() = isCopyCreatedInScope || origin == FirDeclarationOrigin.Enhancement
|
||||
|
||||
val FirCallableSymbol<*>.isIntersectionOverride: Boolean get() = origin == FirDeclarationOrigin.IntersectionOverride
|
||||
val FirCallableSymbol<*>.isSubstitutionOverride: Boolean get() = origin is FirDeclarationOrigin.SubstitutionOverride
|
||||
|
||||
@@ -54,7 +54,7 @@ open class KotlinClass {
|
||||
}
|
||||
|
||||
class B : Java1() {
|
||||
override fun a(): String? = super.a()
|
||||
override fun a(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = super.a()
|
||||
override val b: String? = super.b
|
||||
override var c: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = super.c
|
||||
override var d: String? = super.d
|
||||
|
||||
Reference in New Issue
Block a user