Skip to content

Simplify lifetime management #347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: remove-stream-scopes
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ internal object RpcDeclarationScanner {
private fun unsupportedDeclaration(service: IrClass, declaration: IrDeclaration, logger: MessageCollector): Nothing? {
logger.report(
severity = CompilerMessageSeverity.LOGGING,
message = "Unsupported declaration in RemoteService interface ${service.name}: ${declaration.dumpKotlinLike()}",
message = "Unsupported declaration in @Rpc interface ${service.name}: ${declaration.dumpKotlinLike()}",
)

return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ internal class RpcIrContext(
getIrClassSymbol("kotlinx.coroutines", "CoroutineScope")
}

val coroutineContext by lazy {
getIrClassSymbol("kotlin.coroutines", "CoroutineContext")
}

val kTypeClass by lazy {
getIrClassSymbol("kotlin.reflect", "KType")
}
Expand All @@ -56,14 +52,6 @@ internal class RpcIrContext(
getIrClassSymbol("kotlinx.coroutines.flow", "Flow")
}

val sharedFlow by lazy {
getIrClassSymbol("kotlinx.coroutines.flow", "SharedFlow")
}

val stateFlow by lazy {
getIrClassSymbol("kotlinx.coroutines.flow", "StateFlow")
}

val pair by lazy {
getIrClassSymbol("kotlin", "Pair")
}
Expand Down Expand Up @@ -139,10 +127,6 @@ internal class RpcIrContext(
rpcClient.namedFunction("callServerStreaming")
}

val provideStubContext by lazy {
rpcClient.namedFunction("provideStubContext")
}

val asArray by lazy {
rpcMethodClass.namedFunction("asArray")
}
Expand All @@ -155,10 +139,6 @@ internal class RpcIrContext(
namedFunction("kotlin", "emptyArray")
}

val scopedClientCall by lazy {
namedFunction("kotlinx.rpc.internal", "scopedClientCall")
}

val emptyList by lazy {
namedFunction("kotlin.collections", "emptyList")
}
Expand Down Expand Up @@ -201,10 +181,6 @@ internal class RpcIrContext(
val properties = Properties()

inner class Properties {
val rpcClientCoroutineContext by lazy {
rpcClient.namedProperty("coroutineContext")
}

val rpcServiceDescriptorFqName by lazy {
rpcServiceDescriptor.namedProperty("fqName")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ internal class RpcStubGenerator(
stubIdProperty()

clientProperty()

coroutineContextProperty()
}

private var stubIdProperty: IrProperty by Delegates.notNull()
Expand Down Expand Up @@ -191,64 +189,6 @@ internal class RpcStubGenerator(
}
}

private var coroutineContextProperty: IrProperty by Delegates.notNull()

/**
* `coroutineContext` property from `RemoteService` interface
*
* ```kotlin
* final override val coroutineContext: CoroutineContext = __rpc_client.provideStubContext(__rpc_stub_id)
* ```
*/
private fun IrClass.coroutineContextProperty() {
coroutineContextProperty = addProperty {
name = Name.identifier("coroutineContext")
visibility = DescriptorVisibilities.PUBLIC
modality = Modality.FINAL
}.apply {
overriddenSymbols = listOf(ctx.properties.rpcClientCoroutineContext)

addBackingFieldUtil {
visibility = DescriptorVisibilities.PRIVATE
type = ctx.coroutineContext.defaultType
vsApi { isFinalVS = true }
}.apply {
val coroutineContextClass = ctx.coroutineContext.owner

initializer = factory.createExpressionBody(
vsApi {
IrCallImplVS(
startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET,
type = coroutineContextClass.typeWith(),
symbol = ctx.functions.provideStubContext.symbol,
valueArgumentsCount = 1,
typeArgumentsCount = 0,
)
}.apply {
arguments {
dispatchReceiver = irCallProperty(stubClass, clientProperty)

values {
+irCallProperty(stubClass, stubIdProperty)
}
}
}
)
}

addDefaultGetter(this@coroutineContextProperty, ctx.irBuiltIns) {
val serviceCoroutineContext = declaration.service.getPropertyGetter("coroutineContext")
?: error(
"RPC services expected to have \"coroutineContext\" property with getter: " +
declaration.service.dump()
)

overriddenSymbols = listOf(serviceCoroutineContext)
}
}
}

private fun IrClass.generateMethods() {
declaration.methods.forEach {
generateRpcMethod(it)
Expand Down Expand Up @@ -307,8 +247,6 @@ internal class RpcStubGenerator(
}
}

val declaredFunction = this

val arguments = method.arguments.memoryOptimizedMap { arg ->
addValueParameter {
name = arg.value.name
Expand All @@ -333,63 +271,19 @@ internal class RpcStubGenerator(
return@irBlockBody
}

+irReturn(
irCall(
callee = ctx.functions.scopedClientCall,
type = method.function.returnType,
).apply {
// suspend lambda
// it's type is not available at runtime, but in fact exists
val lambdaType = ctx.suspendFunction0.typeWith(method.function.returnType)

val functionLambda = factory.buildFun {
origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA
name = SpecialNames.ANONYMOUS
visibility = DescriptorVisibilities.LOCAL
modality = Modality.FINAL
returnType = method.function.returnType
isSuspend = true
}.apply {
parent = declaredFunction

body = irBuilder(symbol).irBlockBody {
val call = irRpcMethodClientCall(
method = method,
functionThisReceiver = functionThisReceiver,
isMethodObject = isMethodObject,
methodClass = methodClass,
arguments = arguments,
)

if (method.function.returnType == ctx.irBuiltIns.unitType) {
+call
} else {
+irReturn(call)
}
}
}

val lambda = IrFunctionExpressionImpl(
startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET,
type = lambdaType,
origin = IrStatementOrigin.LAMBDA,
function = functionLambda,
)

arguments {
types {
+method.function.returnType
}

values {
+irGet(ctx.coroutineScope.defaultType, functionThisReceiver.symbol)

+lambda
}
}
}
val call = irRpcMethodClientCall(
method = method,
functionThisReceiver = functionThisReceiver,
isMethodObject = isMethodObject,
methodClass = methodClass,
arguments = arguments,
)

if (method.function.returnType == ctx.irBuiltIns.unitType) {
+call
} else {
+irReturn(call)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name

object RpcClassId {
val remoteServiceInterface = ClassId(FqName("kotlinx.rpc"), Name.identifier("RemoteService"))
val rpcAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("Rpc"))
val checkedTypeAnnotation = ClassId(FqName("kotlinx.rpc.annotations"), Name.identifier("CheckedTypeAnnotation"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,5 @@ class FirRpcExtensionRegistrar(private val configuration: CompilerConfiguration)
}

+CFactory { FirRpcAdditionalCheckers(it, serializationIsPresent, configuration) }

+SFactory { FirRpcSupertypeGenerator(it, logger) }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

package kotlinx.rpc.codegen

import kotlinx.rpc.codegen.common.RpcClassId
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
Expand All @@ -15,17 +14,11 @@ import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.ClassId

fun FirClassSymbol<*>.isRemoteService(session: FirSession): Boolean = resolvedSuperTypeRefs.any {
it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface)
}

fun FirBasedSymbol<*>.rpcAnnotationSource(
session: FirSession,
predicate: DeclarationPredicate,
Expand Down Expand Up @@ -53,14 +46,6 @@ fun List<FirAnnotation>.rpcAnnotation(session: FirSession, predicate: Declaratio
}
}

fun FirClassSymbol<*>.remoteServiceSupertypeSource(session: FirSession): KtSourceElement? {
return remoteServiceSupertype(session)?.source
}

fun FirClassSymbol<*>.remoteServiceSupertype(session: FirSession): FirResolvedTypeRef? {
return resolvedSuperTypeRefs.find { it.doesMatchesClassId(session, RpcClassId.remoteServiceInterface) }
}

@OptIn(SymbolInternals::class)
internal fun FirTypeRef.doesMatchesClassId(session: FirSession, classId: ClassId): Boolean {
return coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session)?.lookupTag?.classId == classId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import kotlinx.rpc.codegen.FirCheckersContext
import kotlinx.rpc.codegen.FirRpcPredicates
import kotlinx.rpc.codegen.checkers.diagnostics.FirRpcDiagnostics
import kotlinx.rpc.codegen.common.RpcClassId
import kotlinx.rpc.codegen.isRemoteService
import kotlinx.rpc.codegen.remoteServiceSupertypeSource
import kotlinx.rpc.codegen.rpcAnnotation
import kotlinx.rpc.codegen.rpcAnnotationSource
import org.jetbrains.kotlin.descriptors.ClassKind
Expand Down Expand Up @@ -51,14 +49,6 @@ object FirRpcAnnotationChecker {
)
}

if (declaration.symbol.isRemoteService(context.session) && !rpcAnnotated) {
reporter.reportOn(
source = declaration.symbol.remoteServiceSupertypeSource(context.session),
factory = FirRpcDiagnostics.MISSING_RPC_ANNOTATION,
context = context,
)
}

if (rpcAnnotated && !ctx.serializationIsPresent && isMetaAnnotated) {
reporter.reportOn(
source = declaration.symbol.rpcAnnotationSource(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.psi.KtElement
// ###########################################################################

object FirRpcDiagnostics : RpcKtDiagnosticsContainer() {
val MISSING_RPC_ANNOTATION by error0<KtAnnotated>()
val MISSING_SERIALIZATION_MODULE by error0<KtAnnotated>()
val WRONG_RPC_ANNOTATION_TARGET by error1<KtAnnotated, ConeKotlinType>()
val CHECKED_ANNOTATION_VIOLATION by error3<KtAnnotated, Int, ConeKotlinType, FirBasedSymbol<*>>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers

object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() {
override val MAP by RpcKtDiagnosticFactoryToRendererMap("Rpc") { map ->
map.put(
factory = FirRpcDiagnostics.MISSING_RPC_ANNOTATION,
message = "Missing @Rpc annotation. " +
"All services children of kotlinx.rpc.RemoteService " +
"must be annotated with kotlinx.rpc.annotations.Rpc",
)

map.put(
factory = FirRpcDiagnostics.MISSING_SERIALIZATION_MODULE,
message = "Missing kotlinx.serialization plugin in the module. " +
Expand Down
Loading