Skip to content

Commit

Permalink
Remove decoys from Compose compiler
Browse files Browse the repository at this point in the history
Decoys are no longer supported / required for JS compilation.

Relnote: Decoy support for JS target is removed from Compose compiler
  • Loading branch information
ShikaSD authored and Space Cloud committed Aug 13, 2024
1 parent 0fc622e commit 83c48a0
Show file tree
Hide file tree
Showing 15 changed files with 68 additions and 1,206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ abstract class KotlinCompilerFacade(val environment: KotlinCoreEnvironment) {
disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES
)

ComposePluginRegistrar.checkCompilerVersion(configuration)
ComposePluginRegistrar.checkCompilerConfiguration(configuration)

environment.project.registerExtensions(configuration)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,25 @@ import androidx.compose.compiler.plugins.kotlin.analysis.FqNameMatcher
import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
import androidx.compose.compiler.plugins.kotlin.k1.ComposeDescriptorSerializerContext
import androidx.compose.compiler.plugins.kotlin.lower.*
import androidx.compose.compiler.plugins.kotlin.lower.decoys.CreateDecoysTransformer
import androidx.compose.compiler.plugins.kotlin.lower.decoys.RecordDecoySignaturesTransformer
import androidx.compose.compiler.plugins.kotlin.lower.decoys.SubstituteDecoyCallsTransformer
import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.AddHiddenFromObjCLowering
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureFactory
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.backend.common.validateIr
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.IrVerificationMode
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsGlobalDeclarationTable
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.isNative
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe

class ComposeIrGenerationExtension(
@Suppress("unused") private val liveLiteralsEnabled: Boolean = false,
@Suppress("unused") private val liveLiteralsV2Enabled: Boolean = false,
private val generateFunctionKeyMetaClasses: Boolean = false,
private val sourceInformationEnabled: Boolean = true,
private val traceMarkersEnabled: Boolean = true,
private val decoysEnabled: Boolean = false,
private val metricsDestination: String? = null,
private val reportsDestination: String? = null,
private val irVerificationMode: IrVerificationMode = IrVerificationMode.NONE,
Expand Down Expand Up @@ -176,50 +164,13 @@ class ComposeIrGenerationExtension(
featureFlags,
).lower(moduleFragment)

val mangler = when {
pluginContext.platform.isJs() -> JsManglerIr
else -> null
}

val idSignatureBuilder = when {
pluginContext.platform.isJs() -> IdSignatureFactory(
PublicIdSignatureComputer(mangler!!),
DeclarationTable(JsGlobalDeclarationTable(pluginContext.irBuiltIns))
)
else -> null
}
if (decoysEnabled) {
require(idSignatureBuilder != null) {
"decoys are not supported for ${pluginContext.platform}"
}

CreateDecoysTransformer(
pluginContext,
symbolRemapper,
idSignatureBuilder,
stabilityInferencer,
metrics,
featureFlags,
).lower(moduleFragment)

SubstituteDecoyCallsTransformer(
pluginContext,
symbolRemapper,
idSignatureBuilder,
stabilityInferencer,
metrics,
featureFlags,
).lower(moduleFragment)
}

// transform all composable functions to have an extra synthetic composer
// parameter. this will also transform all types and calls to include the extra
// parameter.
ComposerParamTransformer(
pluginContext,
symbolRemapper,
stabilityInferencer,
decoysEnabled,
metrics,
featureFlags,
).lower(moduleFragment)
Expand All @@ -234,7 +185,7 @@ class ComposeIrGenerationExtension(

// transform calls to the currentComposer to just use the local parameter from the
// previous transform
ComposerIntrinsicTransformer(pluginContext, decoysEnabled).lower(moduleFragment)
ComposerIntrinsicTransformer(pluginContext).lower(moduleFragment)

ComposableFunctionBodyTransformer(
pluginContext,
Expand All @@ -246,22 +197,6 @@ class ComposeIrGenerationExtension(
featureFlags,
).lower(moduleFragment)

if (decoysEnabled) {
require(idSignatureBuilder != null) {
"decoys are not supported for ${pluginContext.platform}"
}

RecordDecoySignaturesTransformer(
pluginContext,
symbolRemapper,
idSignatureBuilder,
metrics,
mangler!!,
stabilityInferencer,
featureFlags,
).lower(moduleFragment)
}

if (isKlibTarget) {
KlibAssignableParamTransformer(
pluginContext,
Expand All @@ -277,9 +212,7 @@ class ComposeIrGenerationExtension(
pluginContext,
symbolRemapper,
metrics,
idSignatureBuilder,
stabilityInferencer,
decoysEnabled,
featureFlags,
).lower(moduleFragment)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ class ComposePluginRegistrar : CompilerPluginRegistrar() {
get() = true

override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
if (checkCompilerVersion(configuration)) {
if (checkCompilerConfiguration(configuration)) {
val usesK2 = configuration.languageVersionSettings.languageVersion.usesK2
val descriptorSerializerContext =
if (usesK2) null
Expand All @@ -553,7 +553,7 @@ class ComposePluginRegistrar : CompilerPluginRegistrar() {
}

companion object {
fun checkCompilerVersion(configuration: CompilerConfiguration): Boolean {
fun checkCompilerConfiguration(configuration: CompilerConfiguration): Boolean {
val msgCollector = configuration.messageCollector
val suppressKotlinVersionCheck = configuration.get(ComposeConfiguration.SUPPRESS_KOTLIN_VERSION_COMPATIBILITY_CHECK)
if (suppressKotlinVersionCheck != null) {
Expand All @@ -568,7 +568,7 @@ class ComposePluginRegistrar : CompilerPluginRegistrar() {
if (decoysEnabled) {
msgCollector.report(
CompilerMessageSeverity.ERROR,
"Decoys generation should be disabled for Compose Multiplatform projects"
"Decoys generation is no longer supported by the Compose compiler."
)
return false
}
Expand Down Expand Up @@ -635,9 +635,6 @@ class ComposePluginRegistrar : CompilerPluginRegistrar() {
ComposeConfiguration.NON_SKIPPING_GROUP_OPTIMIZATION_ENABLED_KEY,
FeatureFlag.OptimizeNonSkippingGroups.default
)
val decoysEnabled = configuration.getBoolean(
ComposeConfiguration.DECOYS_ENABLED_KEY,
)
val metricsDestination = configuration.get(
ComposeConfiguration.METRICS_DESTINATION_KEY,
""
Expand Down Expand Up @@ -714,7 +711,6 @@ class ComposePluginRegistrar : CompilerPluginRegistrar() {
generateFunctionKeyMetaClasses = generateFunctionKeyMetaClasses,
sourceInformationEnabled = sourceInformationEnabled,
traceMarkersEnabled = traceMarkersEnabled,
decoysEnabled = decoysEnabled,
metricsDestination = metricsDestination,
reportsDestination = reportsDestination,
irVerificationMode = irVerificationMode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@ package androidx.compose.compiler.plugins.kotlin.lower

import androidx.compose.compiler.plugins.kotlin.*
import androidx.compose.compiler.plugins.kotlin.analysis.*
import androidx.compose.compiler.plugins.kotlin.lower.decoys.copyWithNewTypeParams
import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.hiddenFromObjCClassId
import org.jetbrains.kotlin.GeneratedDeclarationKey
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.fir.declarations.utils.klibSourceFile
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
Expand All @@ -50,6 +49,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.library.metadata.DeserializedSourceFile
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
Expand Down Expand Up @@ -1577,3 +1577,28 @@ inline fun <T> includeFileNameInExceptionTrace(file: IrFile, body: () -> T): T {

fun FqName.topLevelName() =
asString().substringBefore(".")

internal inline fun <reified T : IrElement> T.copyWithNewTypeParams(
source: IrFunction,
target: IrFunction
): T {
val typeParamsAwareSymbolRemapper = object : DeepCopySymbolRemapper() {
init {
for ((orig, new) in source.typeParameters.zip(target.typeParameters)) {
typeParameters[orig.symbol] = new.symbol
}
}
}
val typeRemapper = DeepCopyTypeRemapper(typeParamsAwareSymbolRemapper)
val typeParamRemapper = object : TypeRemapper by typeRemapper {
override fun remapType(type: IrType): IrType {
return typeRemapper.remapType(type.remapTypeParameters(source, target))
}
}

val deepCopy = DeepCopyPreservingMetadata(typeParamsAwareSymbolRemapper, typeParamRemapper)
typeRemapper.deepCopy = deepCopy

acceptVoid(typeParamsAwareSymbolRemapper)
return transform(deepCopy, null).patchDeclarationParents(target) as T
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package androidx.compose.compiler.plugins.kotlin.lower
import androidx.compose.compiler.plugins.kotlin.*
import androidx.compose.compiler.plugins.kotlin.analysis.*
import androidx.compose.compiler.plugins.kotlin.lower.ComposerParamTransformer.ComposeDefaultValueStubOrigin
import androidx.compose.compiler.plugins.kotlin.lower.decoys.DecoyFqNames
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
Expand Down Expand Up @@ -2871,8 +2870,7 @@ class ComposableFunctionBodyTransformer(
visitNormalComposableCall(expression)
}
}
ComposeFqNames.key,
DecoyFqNames.key -> visitKeyCall(expression)
ComposeFqNames.key -> visitKeyCall(expression)
else -> visitNormalComposableCall(expression)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package androidx.compose.compiler.plugins.kotlin.lower

import androidx.compose.compiler.plugins.kotlin.hasComposableAnnotation
import androidx.compose.compiler.plugins.kotlin.isComposableAnnotation
import androidx.compose.compiler.plugins.kotlin.lower.decoys.isDecoy
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.peek
Expand Down Expand Up @@ -96,7 +95,7 @@ internal class DeepCopyIrTreeWithRemappedComposableTypes(
// so we potentially need to update composable types for it.
// if the function is in the current module, it should be updated eventually
// by this deep copy pass.
if (overriddenFn.needsComposableRemapping() && !overriddenFn.isDecoy()) {
if (overriddenFn.needsComposableRemapping()) {
overriddenFn.remapTypes(typeRemapper)
}
}
Expand Down Expand Up @@ -412,7 +411,7 @@ class ComposerTypeRemapper(
if (!name.startsWith("Function")) return false
val packageFqName = cls.owner.packageFqName
return packageFqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME ||
packageFqName == KotlinFunctionsBuiltInsPackageFqName
packageFqName == KotlinFunctionsBuiltInsPackageFqName
}

private fun IrType.isComposableFunction(): Boolean {
Expand All @@ -422,10 +421,6 @@ class ComposerTypeRemapper(
override fun remapType(type: IrType): IrType {
if (type !is IrSimpleType) return type
if (!type.isComposableFunction()) return underlyingRemapType(type)
// do not convert types for decoys
if (scopeStack.peek()?.isDecoy() == true) {
return underlyingRemapType(type)
}

val oldIrArguments = type.arguments
val realParams = oldIrArguments.size - 1
Expand All @@ -442,8 +437,8 @@ class ComposerTypeRemapper(
}
val newIrArguments =
oldIrArguments.subList(0, oldIrArguments.size - 1) +
extraArgs +
oldIrArguments.last()
extraArgs +
oldIrArguments.last()

val newArgSize = oldIrArguments.size - 1 + extraArgs.size
val functionCls = context.function(newArgSize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package androidx.compose.compiler.plugins.kotlin.lower

import androidx.compose.compiler.plugins.kotlin.ComposeFqNames
import androidx.compose.compiler.plugins.kotlin.lower.decoys.DecoyFqNames
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.declarations.IrFile
Expand All @@ -35,7 +34,6 @@ import org.jetbrains.kotlin.name.FqName

class ComposerIntrinsicTransformer(
val context: IrPluginContext,
private val decoysEnabled: Boolean
) :
IrElementTransformerVoid(),
FileLoweringPass,
Expand All @@ -45,11 +43,7 @@ class ComposerIntrinsicTransformer(

// get-currentComposer gets transformed as decoy, as the getter now has additional params
private fun currentComposerFqName(): FqName =
if (decoysEnabled) {
DecoyFqNames.CurrentComposerIntrinsic
} else {
ComposeFqNames.CurrentComposerIntrinsic
}
ComposeFqNames.CurrentComposerIntrinsic

override fun lower(module: IrModuleFragment) {
module.transformChildrenVoid(this)
Expand All @@ -65,7 +59,7 @@ class ComposerIntrinsicTransformer(
// to this call is the composer itself. We just replace this expression with the
// argument expression and we are good.
val expectedArgumentsCount = 1 + // composer parameter
1 // changed parameter
1 // changed parameter
assert(expression.valueArgumentsCount == expectedArgumentsCount) {
"""
Composer call doesn't match expected argument count:
Expand Down
Loading

0 comments on commit 83c48a0

Please sign in to comment.