[FIR Java] Add better type parameter erasure for override matching
Around KT-42601
This commit is contained in:
@@ -44,20 +44,48 @@ class JavaOverrideChecker internal constructor(
|
|||||||
substitutor
|
substitutor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private fun Collection<FirTypeParameterRef>.buildErasure() = associate {
|
||||||
|
val symbol = it.symbol
|
||||||
|
val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound
|
||||||
|
symbol to firstBound.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirTypeRef?.isTypeParameterDependent(): Boolean =
|
||||||
|
this is FirResolvedTypeRef && type.lowerBoundIfFlexible() is ConeTypeParameterType
|
||||||
|
|
||||||
|
private fun FirCallableMemberDeclaration<*>.isTypeParameterDependent(): Boolean =
|
||||||
|
typeParameters.isNotEmpty() || returnTypeRef.isTypeParameterDependent() ||
|
||||||
|
receiverTypeRef.isTypeParameterDependent() ||
|
||||||
|
this is FirSimpleFunction && valueParameters.any { it.returnTypeRef.isTypeParameterDependent() }
|
||||||
|
|
||||||
|
private fun FirTypeRef.extractTypeParametersTo(result: MutableCollection<FirTypeParameterRef>) {
|
||||||
|
if (this is FirResolvedTypeRef) {
|
||||||
|
(type.lowerBoundIfFlexible() as? ConeTypeParameterType)?.lookupTag?.typeParameterSymbol?.fir?.let {
|
||||||
|
result += it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirCallableMemberDeclaration<*>.extractTypeParametersTo(result: MutableCollection<FirTypeParameterRef>) {
|
||||||
|
result += typeParameters
|
||||||
|
returnTypeRef.extractTypeParametersTo(result)
|
||||||
|
receiverTypeRef?.extractTypeParametersTo(result)
|
||||||
|
if (this is FirSimpleFunction) {
|
||||||
|
this.valueParameters.forEach { it.returnTypeRef.extractTypeParametersTo(result) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun buildTypeParametersSubstitutorIfCompatible(
|
override fun buildTypeParametersSubstitutorIfCompatible(
|
||||||
overrideCandidate: FirCallableMemberDeclaration<*>,
|
overrideCandidate: FirCallableMemberDeclaration<*>,
|
||||||
baseDeclaration: FirCallableMemberDeclaration<*>
|
baseDeclaration: FirCallableMemberDeclaration<*>
|
||||||
): ConeSubstitutor? {
|
): ConeSubstitutor? {
|
||||||
|
if (!overrideCandidate.isTypeParameterDependent() && !baseDeclaration.isTypeParameterDependent()) {
|
||||||
if (overrideCandidate.typeParameters.isEmpty() && baseDeclaration.typeParameters.isEmpty()) return ConeSubstitutor.Empty
|
return ConeSubstitutor.Empty
|
||||||
|
}
|
||||||
val typeParametersErasure =
|
val typeParameters = linkedSetOf<FirTypeParameterRef>()
|
||||||
(overrideCandidate.typeParameters + baseDeclaration.typeParameters).associate {
|
overrideCandidate.extractTypeParametersTo(typeParameters)
|
||||||
val symbol = it.symbol
|
baseDeclaration.extractTypeParametersTo(typeParameters)
|
||||||
val firstBound = symbol.fir.bounds.first() // Note that in Java type parameter typed arguments always erased to first bound
|
return substitutorByMap(typeParameters.buildErasure())
|
||||||
symbol to firstBound.toConeKotlinTypeProbablyFlexible(session, javaTypeParameterStack)
|
|
||||||
}
|
|
||||||
return substitutorByMap(typeParametersErasure)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user