[FIR2IR] Properly generate GetObject expression for callable reference on companion object

^KT-55909 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-02-02 13:03:34 +02:00
committed by Space Team
parent 80b48eed0b
commit 075e025452
13 changed files with 280 additions and 1 deletions
@@ -13,13 +13,16 @@ import org.jetbrains.kotlin.fir.dispatchReceiverClassLookupTagOrNull
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.getContainingClassLookupTag
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.approximateDeclarationType
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
@@ -703,7 +706,35 @@ class CallAndReferenceGenerator(
val resolvedReference = callableReferenceAccess.calleeReference as FirResolvedNamedReference
val firCallableSymbol = resolvedReference.resolvedSymbol as FirCallableSymbol<*>
// Make sure the reference indeed refers to a member of that companion
if (firCallableSymbol.dispatchReceiverClassLookupTagOrNull() != classSymbol.toLookupTag()) {
val dispatchReceiverClassLookupTag = firCallableSymbol.dispatchReceiverClassLookupTagOrNull() ?: return null
val callableIsDefinitelyNotMemberOfCompanion = with(session.typeContext) {
!classSymbol.defaultType().anySuperTypeConstructor { it.typeConstructor() == dispatchReceiverClassLookupTag }
}
if (callableIsDefinitelyNotMemberOfCompanion) {
return null
}
/*
* This check is supposed to distinguish cases when both companion and containing class have this function
*
* open class Base {
* fun foo() {}
* }
*
* class Some : Base() {
* companion object : Base() {
* fun bar()
* }
* }
*
* Some::foo // reference to Some.foo
* Some::bar // reference to Some.Companion.bar
*/
val containingClass = classSymbol.getContainingClassLookupTag()?.toFirRegularClassSymbol(session) ?: return null
val callableIsDefinitelyMemberOfOuterClass = with(session.typeContext) {
containingClass.defaultType().anySuperTypeConstructor { it.typeConstructor() == dispatchReceiverClassLookupTag }
}
if (callableIsDefinitelyMemberOfOuterClass) {
return null
}
}
@@ -4656,6 +4656,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/callableReference/serializability/noReflect.kt");
}
@Test
@TestMetadata("referenceToCompanionFunction.kt")
public void testReferenceToCompanionFunction() throws Exception {
runTest("compiler/testData/codegen/box/callableReference/serializability/referenceToCompanionFunction.kt");
}
@Test
@TestMetadata("reflectedIsNotSerialized.kt")
public void testReflectedIsNotSerialized() throws Exception {