[FIR] fixed overridden symbols of "invoke" in KFunction

IR expects overridden symbols of "invoke" in KFunction to be "invoke"
in the corresponding Function classes.
Before this commit we don't set overriddenSymbol, now we do.
This commit is contained in:
Juan Chen
2020-02-07 13:52:01 -08:00
committed by Mikhail Glukhikh
parent e3721ed406
commit 04e8cba857
32 changed files with 58 additions and 69 deletions
@@ -16,13 +16,8 @@ import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor import org.jetbrains.kotlin.fir.descriptors.FirPackageFragmentDescriptor
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.firProvider import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.resolve.getOrPut
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.arrayElementType import org.jetbrains.kotlin.fir.types.arrayElementType
@@ -421,11 +416,12 @@ class Fir2IrDeclarationStorage(
fun create(): IrSimpleFunction { fun create(): IrSimpleFunction {
val containerSource = function.containerSource val containerSource = function.containerSource
val descriptor = containerSource?.let { WrappedFunctionDescriptorWithContainerSource(it) } ?: WrappedSimpleFunctionDescriptor() val descriptor = containerSource?.let { WrappedFunctionDescriptorWithContainerSource(it) } ?: WrappedSimpleFunctionDescriptor()
val updatedOrigin = if (function.symbol.callableId.isKFunctionInvoke()) IrDeclarationOrigin.FAKE_OVERRIDE else origin
return function.convertWithOffsets { startOffset, endOffset -> return function.convertWithOffsets { startOffset, endOffset ->
enterScope(descriptor) enterScope(descriptor)
val result = irSymbolTable.declareSimpleFunction(startOffset, endOffset, origin, descriptor) { symbol -> val result = irSymbolTable.declareSimpleFunction(startOffset, endOffset, origin, descriptor) { symbol ->
IrFunctionImpl( IrFunctionImpl(
startOffset, endOffset, origin, symbol, startOffset, endOffset, updatedOrigin, symbol,
function.name, function.visibility, function.modality!!, function.name, function.visibility, function.modality!!,
function.returnTypeRef.toIrType(session, this), function.returnTypeRef.toIrType(session, this),
isInline = function.isInline, isInline = function.isInline,
@@ -433,7 +429,7 @@ class Fir2IrDeclarationStorage(
isTailrec = function.isTailRec, isTailrec = function.isTailRec,
isSuspend = function.isSuspend, isSuspend = function.isSuspend,
isExpect = function.isExpect, isExpect = function.isExpect,
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE, isFakeOverride = updatedOrigin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = function.isOperator isOperator = function.isOperator
) )
} }
@@ -775,6 +771,11 @@ class Fir2IrDeclarationStorage(
is FirSimpleFunction -> { is FirSimpleFunction -> {
val irDeclaration = getIrFunction(firDeclaration, irParent, shouldLeaveScope = true).apply { val irDeclaration = getIrFunction(firDeclaration, irParent, shouldLeaveScope = true).apply {
setAndModifyParent(irParent) setAndModifyParent(irParent)
} as IrSimpleFunction
if (firFunctionSymbol.callableId.isKFunctionInvoke()) {
(firFunctionSymbol.overriddenSymbol as? FirNamedFunctionSymbol)?.let {
irDeclaration.overriddenSymbols += (it.toFunctionSymbol(this) as IrSimpleFunctionSymbol)
}
} }
irSymbolTable.referenceSimpleFunction(irDeclaration.descriptor) irSymbolTable.referenceSimpleFunction(irDeclaration.descriptor)
} }
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.FirResolvedQualifierBuilder
import org.jetbrains.kotlin.fir.expressions.builder.FirResolvedReifiedParameterReferenceBuilder import org.jetbrains.kotlin.fir.expressions.builder.FirResolvedReifiedParameterReferenceBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -463,6 +462,12 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc
} }
fun CallableId.isInvoke() = fun CallableId.isInvoke() =
packageName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME isKFunctionInvoke()
|| callableName.asString() == "invoke"
&& className?.asString()?.startsWith("Function") == true && className?.asString()?.startsWith("Function") == true
&& callableName.asString() == "invoke" && packageName == KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME
fun CallableId.isKFunctionInvoke() =
callableName.asString() == "invoke"
&& className?.asString()?.startsWith("KFunction") == true
&& packageName.asString() == "kotlin.reflect"
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildClassImpl import org.jetbrains.kotlin.fir.declarations.builder.buildClassImpl
@@ -209,30 +206,11 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) type = ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
} }
} }
val superKind: FunctionClassDescriptor.Kind? = when (kind) {
addDeclaration( FunctionClassDescriptor.Kind.KFunction -> FunctionClassDescriptor.Kind.Function
buildSimpleFunction { FunctionClassDescriptor.Kind.KSuspendFunction -> FunctionClassDescriptor.Kind.SuspendFunction
session = this@FirBuiltinSymbolProvider.session else -> null
returnTypeRef = typeArguments.last() }
this.name = name
status = functionStatus
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, relativeClassName, name))
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
val parameterName = Name.identifier("p${index + 1}")
buildValueParameter {
session = this@FirBuiltinSymbolProvider.session
returnTypeRef = typeArgument
this.name = parameterName
symbol = FirVariableSymbol(parameterName)
defaultValue = null
isCrossinline = false
isNoinline = false
isVararg = false
}
}
},
)
fun createSuperType( fun createSuperType(
kind: FunctionClassDescriptor.Kind, kind: FunctionClassDescriptor.Kind,
@@ -259,12 +237,46 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
FunctionClassDescriptor.Kind.KSuspendFunction -> FunctionClassDescriptor.Kind.KSuspendFunction ->
createSuperType(FunctionClassDescriptor.Kind.SuspendFunction) createSuperType(FunctionClassDescriptor.Kind.SuspendFunction)
} }
addDeclaration(
buildSimpleFunction {
session = this@FirBuiltinSymbolProvider.session
returnTypeRef = typeArguments.last()
this.name = name
status = functionStatus
symbol = FirNamedFunctionSymbol(
CallableId(packageFqName, relativeClassName, name),
// set overriddenSymbol for "invoke" of KFunction/KSuspendFunction
superKind != null, superKind?.getInvoke(arity)
)
resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
valueParameters += typeArguments.dropLast(1).mapIndexed { index, typeArgument ->
val parameterName = Name.identifier("p${index + 1}")
buildValueParameter {
session = this@FirBuiltinSymbolProvider.session
returnTypeRef = typeArgument
this.name = parameterName
symbol = FirVariableSymbol(parameterName)
defaultValue = null
isCrossinline = false
isNoinline = false
isVararg = false
}
}
}
)
} }
} }
} }
} }
} }
// Find the symbol for "invoke" in the function class
private fun FunctionClassDescriptor.Kind.getInvoke(arity: Int): FirNamedFunctionSymbol? {
val functionClass = getClassLikeSymbolByFqName(classId(arity)) ?: return null
val invoke =
functionClass.fir.declarations.find { it is FirSimpleFunction && it.name == OperatorNameConventions.INVOKE } ?: return null
return (invoke as FirSimpleFunction).symbol as? FirNamedFunctionSymbol
}
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? { override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullResult { return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class A { abstract class A {
abstract fun foo(): String abstract fun foo(): String
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
fun foo(k: Int) = k fun foo(k: Int) = k
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
fun o() = 111 fun o() = 111
fun k(k: Int) = k fun k(k: Int) = k
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
fun foo() = "OK" fun foo() = "OK"
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
fun foo(result: String) = result fun foo(result: String) = result
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
var result = "Fail" var result = "Fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
var result = "Fail" var result = "Fail"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
var result = "OK" var result = "OK"
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A(val result: String) class A(val result: String)
fun box() = (::A)("OK").result fun box() = (::A)("OK").result
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A class A
fun box() = if ((A::equals)(A(), A())) "Fail" else "OK" fun box() = if ((A::equals)(A(), A())) "Fail" else "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
fun result() = (A::foo)(this, "OK") fun result() = (A::foo)(this, "OK")
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A class A
fun A.foo() = (A::bar)(this, "OK") fun A.foo() = (A::bar)(this, "OK")
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun run(arg1: A, funRef:A.() -> String): String { fun run(arg1: A, funRef:A.() -> String): String {
return arg1.funRef() return arg1.funRef()
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun run(arg1: A, arg2: String, funRef:A.(String) -> String): String { fun run(arg1: A, arg2: String, funRef:A.(String) -> String): String {
return arg1.funRef(arg2) return arg1.funRef(arg2)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
var result = "Fail" var result = "Fail"
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun run(arg1: A, arg2: String, funRef:A.(String) -> Unit): Unit { fun run(arg1: A, arg2: String, funRef:A.(String) -> Unit): Unit {
return arg1.funRef(arg2) return arg1.funRef(arg2)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String { fun box(): String {
class A { class A {
val result = "OK" val result = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String { fun box(): String {
class A { class A {
var result: String = "Fail"; var result: String = "Fail";
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
class Nested { class Nested {
val result = "OK" val result = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
class Nested(val result: String) class Nested(val result: String)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
private fun foo() = "OK" private fun foo() = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun <T> run(arg1: T, arg2: T, funRef:(T,T) -> T): T { fun <T> run(arg1: T, arg2: T, funRef:(T,T) -> T): T {
return funRef(arg1, arg2) return funRef(arg1, arg2)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun <T> run(arg1: T, arg2: T, funRef:(T,T) -> T): T { fun <T> run(arg1: T, arg2: T, funRef:(T,T) -> T): T {
return funRef(arg1, arg2) return funRef(arg1, arg2)
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
fun foo(x: String) = x fun foo(x: String) = x
fun box(): String { fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
var result = "Fail" var result = "Fail"
fun foo() { fun foo() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
var result = "Fail" var result = "Fail"
fun foo(newResult: String) { fun foo(newResult: String) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A { interface A {
fun foo(): String fun foo(): String
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS // IGNORE_LIGHT_ANALYSIS
// WITH_RUNTIME // WITH_RUNTIME