Repository: JetBrains/kotlin
File: plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt (Kotlin)

Code before:
                    )
                }
            }

            val stubs = fn.makeStubsForDefaultValueClassIfNeeded()

            // update parameter types so they are ready to accept the default values
            fn.parameters.fastForEach { param ->
                if (fn.hasDefaultForParam(param.indexInParameters)) {
                    param.type = param.type.defaultParameterType()
                }
            }

            val parent = fn.parent
            if (parent is IrClass || parent is IrFile) {

                fun IrSimpleFunction.toComparableParams(): List<Pair<IrClassifierSymbol, SimpleTypeNullability>?> =
                    parameters.map {
                        when (val paramType = it.type) {
                            is IrSimpleType ->
                                if (paramType.classifier is IrTypeParameterSymbol) {
                                    val typeParam = paramType.classifier.owner as IrTypeParameter
                                    // if a type parameter is defined on a stub,
                                    // it should be compared with matching original function's type parameter
                                    // instead of comparing each stub's type parameters
                                    val classifier = if (typeParam.parent == this) {
                                        fn.typeParameters[typeParam.index].symbol
                                    } else {
                                        paramType.classifier
                                    }
                                    Pair(classifier, paramType.nullability)

                                } else {
                                    Pair(paramType.classifier, paramType.nullability)
                                }
                            else -> null
                        }
                    }

                // checking if any stubs have all same-type parameters and discarding them
                val addedParamTypes = mutableSetOf(fn.toComparableParams())
                stubs.forEach { stub ->
                    val stubParamTypes = stub.toComparableParams()
                    if (addedParamTypes.add(stubParamTypes)) {
                        parent.addChild(stub)
                    }
                }
            } else {
                // ignore
            }


Review comment (bug):
Does this mean that we don't copy type parameters to stubs? Technically, that produces incorrect IR, if I read this correctly.

Code after:
                name = ComposeNames.ComposerParameter
                type = composerType.makeNullable()
                origin = IrDeclarationOrigin.DEFINED
                isAssignable = true
            }

            // $changed[n]
            val changed = ComposeNames.ChangedParameter.identifier
            for (i in 0 until changedParamCount(realParams, fn.thisParamCount)) {
                fn.addValueParameter(
                    if (i == 0) changed else "$changed$i",
                    context.irBuiltIns.intType
                )
            }

            // $default[n]
            if (fn.requiresDefaultParameter()) {
                val defaults = ComposeNames.DefaultParameter.identifier
                for (i in 0 until defaultParamCount(currentParams)) {
                    fn.addValueParameter(
                        if (i == 0) defaults else "$defaults$i",
                        context.irBuiltIns.intType,
                        IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION
                    )
                }
            }

            val stubs = fn.makeStubsForDefaultValueClassIfNeeded()

            // update parameter types so they are ready to accept the default values
            fn.parameters.fastForEach { param ->
                if (fn.hasDefaultForParam(param.indexInParameters)) {
                    param.type = param.type.defaultParameterType()
                }
            }

            val parent = fn.parent
            if (parent is IrClass || parent is IrFile) {
                // checking if any stubs have all same-type parameters and discarding them
                val addedParamTypes = mutableSetOf(fn.toComparableParams(fn))
                stubs.forEach { stub ->
                    val stubParamTypes = stub.toComparableParams(fn)
                    if (addedParamTypes.add(stubParamTypes)) {
                        parent.addChild(stub)
                    }
                }
            } else {
                // ignore
            }

            inlineLambdaInfo.scan(fn)