[FIR] Remove FirDeclarationsForMetadataProviderExtension extension
`IrGeneratedDeclarationsRegistrar` should be now used instead to register IR declarations in resulting metadata
This commit is contained in:
-11
@@ -34,7 +34,6 @@ abstract class FirExtensionRegistrar : FirExtensionRegistrarAdapter() {
|
||||
FirScriptConfiguratorExtension::class,
|
||||
Fir2IrScriptConfiguratorExtension::class,
|
||||
FirFunctionTypeKindExtension::class,
|
||||
FirDeclarationsForMetadataProviderExtension::class,
|
||||
)
|
||||
|
||||
internal val ALLOWED_EXTENSIONS_FOR_LIBRARY_SESSION = listOf(
|
||||
@@ -108,11 +107,6 @@ abstract class FirExtensionRegistrar : FirExtensionRegistrarAdapter() {
|
||||
registerExtension(FirFunctionTypeKindExtension::class, this)
|
||||
}
|
||||
|
||||
@JvmName("plusDeclarationForMetadataProviderExtension")
|
||||
operator fun (FirDeclarationsForMetadataProviderExtension.Factory).unaryPlus() {
|
||||
registerExtension(FirDeclarationsForMetadataProviderExtension::class, this)
|
||||
}
|
||||
|
||||
// ------------------ reference methods ------------------
|
||||
|
||||
@JvmName("plusStatusTransformerExtension")
|
||||
@@ -175,11 +169,6 @@ abstract class FirExtensionRegistrar : FirExtensionRegistrarAdapter() {
|
||||
FirFunctionTypeKindExtension.Factory { this.invoke(it) }.unaryPlus()
|
||||
}
|
||||
|
||||
@JvmName("plusDeclarationForMetadataProviderExtension")
|
||||
operator fun ((FirSession) -> FirDeclarationsForMetadataProviderExtension).unaryPlus() {
|
||||
FirDeclarationsForMetadataProviderExtension.Factory { this.invoke(it) }.unaryPlus()
|
||||
}
|
||||
|
||||
// ------------------ utilities ------------------
|
||||
|
||||
@JvmName("bindLeft")
|
||||
|
||||
+43
-32
@@ -9,22 +9,57 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.declarationForMetadataProviders
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||
|
||||
|
||||
/**
|
||||
* This extension can be used to provide information about declarations, which should be written in Kotlin metadata (i.e. be part of a module's ABI),
|
||||
* but for some reason can not (or should not) be generated with [FirDeclarationGenerationExtension]
|
||||
*
|
||||
* Example: assume your plugin generates some constructor in [IrGenerationExtension] which have value parameters matching
|
||||
* all properties of a class, and this constructor is used only as an implementation detail (so the only actor who accesses it
|
||||
* is a plugin itself). The constructor should be accessible from another module, so it should be present in the metadata. But you
|
||||
* can not generate this constructor in [FirDeclarationGenerationExtension], because it depends on types of properties,
|
||||
* which may be not resolved at the moment of constructor creation.
|
||||
*
|
||||
*
|
||||
* // MODULE: a
|
||||
* open class Base {
|
||||
* val x: Int = 1
|
||||
* val y = "hello"
|
||||
*
|
||||
* constructor()
|
||||
*
|
||||
* // generated
|
||||
* constructor(x: Int, y: String) { ... } // (1)
|
||||
* }
|
||||
*
|
||||
* // MODULE: b(a)
|
||||
* class Derived : Base {
|
||||
* val z = 1.0
|
||||
*
|
||||
* constructor() : super()
|
||||
*
|
||||
* // generated
|
||||
* constructor(x: Int, y: String, z: Double) : super(x, y) { ... } // (2)
|
||||
*
|
||||
* // constructor (1) should be presented in metadata of class Base, so IR plugin
|
||||
* // can reference it during generation of constructor (2)
|
||||
* }
|
||||
*
|
||||
* All declarations provided by this extension should be fully resolved and contain all sub declarations if they exist.
|
||||
* E.g. if you want to provide some class then this class should contain all declarations of this class you want to be
|
||||
* present in metadata in `declarations` field of a `FirRegularClass`.
|
||||
* [FirDeclarationGenerationExtension] won't be called for classes provided by this extension.
|
||||
*/
|
||||
abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
|
||||
companion object {
|
||||
fun create(session: FirSession): FirProvidedDeclarationsForMetadataService {
|
||||
val extensionProviders = session.extensionService.declarationForMetadataProviders
|
||||
return if (extensionProviders.isEmpty()) Empty else FirProvidedDeclarationsForMetadataServiceImpl(session, extensionProviders)
|
||||
return FirProvidedDeclarationsForMetadataServiceImpl(session)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,33 +70,9 @@ abstract class FirProvidedDeclarationsForMetadataService : FirSessionComponent {
|
||||
|
||||
abstract fun registerDeclaration(declaration: FirCallableDeclaration)
|
||||
|
||||
private object Empty : FirProvidedDeclarationsForMetadataService() {
|
||||
override fun getProvidedTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun getProvidedConstructors(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirConstructor> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun getProvidedCallables(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirCallableDeclaration> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun getProvidedNestedClassifiers(owner: FirClassSymbol<*>, scopeSession: ScopeSession): List<FirClassLikeSymbol<*>> {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
override fun registerDeclaration(declaration: FirCallableDeclaration) {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FirProvidedDeclarationsForMetadataServiceImpl(
|
||||
private val session: FirSession,
|
||||
private val extensionDeclarationProviders: List<FirDeclarationsForMetadataProviderExtension>
|
||||
) : FirProvidedDeclarationsForMetadataService() {
|
||||
private class FirProvidedDeclarationsForMetadataServiceImpl(private val session: FirSession) : FirProvidedDeclarationsForMetadataService() {
|
||||
private val topLevelsCache: MutableMap<FqName, MutableList<FirDeclaration>> =
|
||||
mutableMapOf()
|
||||
|
||||
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.extensions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* This extension can be used to provide information about declarations, which should be written in Kotlin metadata (i.e. be part of a module's ABI),
|
||||
* but for some reason can not (or should not) be generated with [FirDeclarationGenerationExtension]
|
||||
*
|
||||
* Example: assume your plugin generates some constructor in [IrGenerationExtension] which have value parameters matching
|
||||
* all properties of a class, and this constructor is used only as an implementation detail (so the only actor who accesses it
|
||||
* is a plugin itself). The constructor should be accessible from another module, so it should be present in the metadata. But you
|
||||
* can not generate this constructor in [FirDeclarationGenerationExtension], because it depends on types of properties,
|
||||
* which may be not resolved at the moment of constructor creation.
|
||||
*
|
||||
*
|
||||
* // MODULE: a
|
||||
* open class Base {
|
||||
* val x: Int = 1
|
||||
* val y = "hello"
|
||||
*
|
||||
* constructor()
|
||||
*
|
||||
* // generated
|
||||
* constructor(x: Int, y: String) { ... } // (1)
|
||||
* }
|
||||
*
|
||||
* // MODULE: b(a)
|
||||
* class Derived : Base {
|
||||
* val z = 1.0
|
||||
*
|
||||
* constructor() : super()
|
||||
*
|
||||
* // generated
|
||||
* constructor(x: Int, y: String, z: Double) : super(x, y) { ... } // (2)
|
||||
*
|
||||
* // constructor (1) should be presented in metadata of class Base, so IR plugin
|
||||
* // can reference it during generation of constructor (2)
|
||||
* }
|
||||
*
|
||||
* All declarations provided by this extension should be fully resolved and contain all sub declarations if they exist.
|
||||
* E.g. if you want to provide some class then this class should contain all declarations of this class you want to be
|
||||
* present in metadata in `declarations` field of a `FirRegularClass`.
|
||||
* [FirDeclarationGenerationExtension] won't be called for classes provided by this extension.
|
||||
*/
|
||||
abstract class FirDeclarationsForMetadataProviderExtension(session: FirSession) : FirExtension(session) {
|
||||
companion object {
|
||||
val NAME = FirExtensionPointName("SyntheticDeclarationsForMetadataGenerationExtension")
|
||||
}
|
||||
|
||||
final override val name: FirExtensionPointName
|
||||
get() = NAME
|
||||
|
||||
final override val extensionType: KClass<out FirExtension> = FirDeclarationsForMetadataProviderExtension::class
|
||||
|
||||
/**
|
||||
* It's allowed to provide only functions, properties and type aliases
|
||||
*/
|
||||
open fun provideTopLevelDeclarations(packageFqName: FqName, scopeSession: ScopeSession): List<FirDeclaration> = emptyList()
|
||||
|
||||
open fun provideDeclarationsForClass(klass: FirClass, scopeSession: ScopeSession): List<FirDeclaration> = emptyList()
|
||||
|
||||
fun interface Factory : FirExtension.Factory<FirDeclarationsForMetadataProviderExtension>
|
||||
}
|
||||
|
||||
val FirExtensionService.declarationForMetadataProviders: List<FirDeclarationsForMetadataProviderExtension> by FirExtensionService.registeredExtensions()
|
||||
-2
@@ -34,8 +34,6 @@ class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() {
|
||||
+::AdditionalMembersGenerator
|
||||
+::CompanionGenerator
|
||||
+::MembersOfSerializerGenerator
|
||||
|
||||
+::AllPropertiesConstructorMetadataProvider
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.plugin.generators
|
||||
|
||||
import org.jetbrains.kotlin.GeneratedDeclarationKey
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.plugin.createConstructor
|
||||
import org.jetbrains.kotlin.fir.plugin.fqn
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.scopes.getProperties
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
|
||||
class AllPropertiesConstructorMetadataProvider(session: FirSession) : FirDeclarationsForMetadataProviderExtension(session) {
|
||||
companion object {
|
||||
val ANNOTATION_FQN = "AllPropertiesConstructor".fqn()
|
||||
val PREDICATE = DeclarationPredicate.create { annotated(ANNOTATION_FQN) }
|
||||
}
|
||||
|
||||
private object Key : GeneratedDeclarationKey()
|
||||
|
||||
override fun provideDeclarationsForClass(klass: FirClass, scopeSession: ScopeSession): List<FirDeclaration> {
|
||||
if (!session.predicateBasedProvider.matches(PREDICATE, klass)) return emptyList()
|
||||
val scope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = null)
|
||||
val properties = scope.getCallableNames()
|
||||
.flatMap { scope.getProperties(it) }
|
||||
.sortedBy { it.containingClassLookupTag() == klass.symbol.toLookupTag() }
|
||||
val constructor = createConstructor(klass.symbol, Key) {
|
||||
for (property in properties) {
|
||||
valueParameter(property.name, property.resolvedReturnType)
|
||||
}
|
||||
}
|
||||
return listOf(constructor)
|
||||
}
|
||||
|
||||
override fun FirDeclarationPredicateRegistrar.registerPredicates() {
|
||||
register(PREDICATE)
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.plugin
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.plugin.generators.AllPropertiesConstructorMetadataProvider
|
||||
import org.jetbrains.kotlin.fir.plugin.fqn
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
|
||||
@@ -29,6 +29,10 @@ import java.util.Comparator
|
||||
* Parent class should be Any or class, annotated with @AllPropertiesConstructor
|
||||
*/
|
||||
class AllPropertiesConstructorIrGenerator(val context: IrPluginContext) : IrElementVisitorVoid {
|
||||
companion object {
|
||||
private val ANNOTATION_FQN = "AllPropertiesConstructor".fqn()
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
@@ -89,8 +93,6 @@ class AllPropertiesConstructorIrGenerator(val context: IrPluginContext) : IrElem
|
||||
}
|
||||
|
||||
private fun IrClass.hasAnnotation(): Boolean {
|
||||
return annotations.findAnnotation(AllPropertiesConstructorMetadataProvider.ANNOTATION_FQN) != null
|
||||
return annotations.hasAnnotation(ANNOTATION_FQN)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -17,7 +17,6 @@ class FirSerializationExtensionRegistrar : FirExtensionRegistrar() {
|
||||
+::SerializationFirResolveExtension
|
||||
+::SerializationFirSupertypesExtension
|
||||
+::FirSerializationCheckersComponent
|
||||
+::SerializationFirDeclarationsForMetadataProvider
|
||||
|
||||
// services
|
||||
+::DependencySerializationInfoProvider
|
||||
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.fir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationsForMetadataProviderExtension
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.plugin.createConstructor
|
||||
import org.jetbrains.kotlin.fir.plugin.createMemberFunction
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.JvmStandardClassIds
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.services.serializablePropertiesProvider
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
|
||||
class SerializationFirDeclarationsForMetadataProvider(session: FirSession) : FirDeclarationsForMetadataProviderExtension(session) {
|
||||
override fun provideDeclarationsForClass(klass: FirClass, scopeSession: ScopeSession): List<FirDeclaration> {
|
||||
// FIXME: multi-field value classes require additional 'if' here, but they're not supported for now in serialization K2.
|
||||
return if (klass.symbol.isInline || with(session) { !klass.symbol.isInternalSerializable }) emptyList()
|
||||
// As we deprecated 'customize serializer via companion', we know for sure
|
||||
// that serialize/deserialize functions are synthetic and generated by our plugin.
|
||||
else listOfNotNull(generateDeserializationConstructor(klass), generateWriteSelf(klass))
|
||||
}
|
||||
|
||||
private fun generateDeserializationConstructor(klass: FirClass): FirDeclaration =
|
||||
createConstructor(klass.symbol, SerializationPluginKey, isPrimary = false) {
|
||||
// deserialization constructor for final classes could be internal, because it can't be called in inheritors
|
||||
visibility = if (klass.isFinal) Visibilities.Internal else Visibilities.Public
|
||||
|
||||
val serializableProperties =
|
||||
session.serializablePropertiesProvider.getSerializablePropertiesForClass(klass.symbol).serializableProperties
|
||||
val bitMaskSlotCount = serializableProperties.bitMaskSlotCount()
|
||||
repeat(bitMaskSlotCount) {
|
||||
valueParameter(Name.identifier("seen$it"), session.builtinTypes.intType.type)
|
||||
}
|
||||
serializableProperties.forEach { prop ->
|
||||
valueParameter(
|
||||
prop.originalDescriptorName,
|
||||
prop.propertySymbol.resolvedReturnType.makeNullableIfNotPrimitive(session.typeContext)
|
||||
)
|
||||
}
|
||||
val markerType =
|
||||
ClassId(SerializationPackages.internalPackageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME).constructClassLikeType(
|
||||
emptyArray(),
|
||||
isNullable = true
|
||||
)
|
||||
valueParameter(SerialEntityNames.dummyParamName, markerType)
|
||||
}
|
||||
|
||||
private fun generateWriteSelf(klass: FirClass): FirDeclaration? {
|
||||
// write$Self in K1 is created only on JVM (see SerializationResolveExtension)
|
||||
if (!session.moduleData.platform.isJvm()) return null
|
||||
return createMemberFunction(
|
||||
klass.symbol,
|
||||
SerializationPluginKey,
|
||||
SerialEntityNames.WRITE_SELF_NAME,
|
||||
session.builtinTypes.unitType.type
|
||||
) {
|
||||
// write$Self for final classes could be internal, because it can't be called in inheritors
|
||||
visibility = if (klass.isFinal) Visibilities.Internal else Visibilities.Public
|
||||
|
||||
klass.typeParameters.forEach {
|
||||
typeParameter(it.symbol.name)
|
||||
}
|
||||
|
||||
valueParameter(Name.identifier("self"), { functionTypeParams ->
|
||||
klass.symbol.constructType(functionTypeParams.map { it.toConeType() }.toTypedArray(), false)
|
||||
})
|
||||
|
||||
valueParameter(
|
||||
Name.identifier("output"),
|
||||
SerializationRuntimeClassIds.compositeEncoderClassId.constructClassLikeType(emptyArray(), false)
|
||||
)
|
||||
|
||||
valueParameter(
|
||||
Name.identifier("serialDesc"),
|
||||
SerializationRuntimeClassIds.descriptorClassId.constructClassLikeType(emptyArray(), false)
|
||||
)
|
||||
|
||||
klass.typeParameters.forEachIndexed { i, _ ->
|
||||
valueParameter(Name.identifier("${SerialEntityNames.typeArgPrefix}$i"), { functionTps ->
|
||||
SerializersClassIds.kSerializerId.constructClassLikeType(arrayOf(functionTps[i].toConeType()), false)
|
||||
})
|
||||
}
|
||||
}.apply { replaceAnnotations(listOfNotNull(createJvmStaticAnnotation())) }
|
||||
}
|
||||
|
||||
private fun createJvmStaticAnnotation(): FirAnnotation? {
|
||||
val jvmStatic =
|
||||
session.symbolProvider.getClassLikeSymbolByClassId(JvmStandardClassIds.Annotations.JvmStatic) as? FirRegularClassSymbol
|
||||
?: return null
|
||||
val jvmStaticCtor =
|
||||
jvmStatic.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>() ?: return null
|
||||
|
||||
return buildAnnotationCall {
|
||||
annotationTypeRef = jvmStatic.defaultType().toFirResolvedTypeRef()
|
||||
calleeReference = buildResolvedNamedReference {
|
||||
name = jvmStatic.name
|
||||
resolvedSymbol = jvmStaticCtor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ConeKotlinType.makeNullableIfNotPrimitive(typeContext: ConeTypeContext): ConeKotlinType =
|
||||
if (isPrimitive) this else withNullability(ConeNullability.NULLABLE, typeContext)
|
||||
Reference in New Issue
Block a user