K2: Attach function parameter annotation to function expression

When a function parameter has an annotation, the exist FIR2IR does not
attach the annotation to the function expression (lambda argument),
which results in a missing annotation. It is critical to the Compose,
because the compose compiler / compose runtime rely on the Composable
annotation.

This commit attaches the annotation of a function parameter to the
function expression used for the argument (like lambda) to fix this
issue.

^KT-64994 Fixed
diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleMultiModuleCompilerFacilityTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleMultiModuleCompilerFacilityTestGenerated.java
index 75c5a0fc..3b6e1ca 100644
--- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleMultiModuleCompilerFacilityTestGenerated.java
+++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/compilerFacility/FirIdeNormalAnalysisSourceModuleMultiModuleCompilerFacilityTestGenerated.java
@@ -64,6 +64,18 @@
         runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/internalUsage.kt");
     }
 
+    @Test
+    @TestMetadata("lambdaParameterWithAnnotation.kt")
+    public void testLambdaParameterWithAnnotation() throws Exception {
+        runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.kt");
+    }
+
+    @Test
+    @TestMetadata("lambdaParameterWithAnnotation2.kt")
+    public void testLambdaParameterWithAnnotation2() throws Exception {
+        runTest("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.kt");
+    }
+
     @Nested
     @TestMetadata("analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/codeFragments")
     @TestDataPath("$PROJECT_ROOT")
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.ir.txt
new file mode 100644
index 0000000..8dff5bc
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.ir.txt
@@ -0,0 +1,26 @@
+MODULE_FRAGMENT
+  FILE fqName:<root> fileName:main.kt
+    FUN name:Greeting visibility:public modality:FINAL <> (name:kotlin.String) returnType:kotlin.Unit
+      annotations:
+        Composable
+      VALUE_PARAMETER name:name index:0 type:kotlin.String
+      BLOCK_BODY
+        CALL 'public final fun show (str: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
+          str: STRING_CONCATENATION type=kotlin.String
+            CONST String type=kotlin.String value="hi "
+            GET_VAR 'name: kotlin.String declared in <root>.Greeting' type=kotlin.String origin=null
+            CONST String type=kotlin.String value="!"
+    FUN name:show visibility:public modality:FINAL <> (str:kotlin.String) returnType:kotlin.Unit
+      VALUE_PARAMETER name:str index:0 type:kotlin.String
+      BLOCK_BODY
+    FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Int
+      BLOCK_BODY
+        RETURN type=kotlin.Nothing from='public final fun test (): kotlin.Int declared in <root>'
+          CALL 'public final fun setContent (content: @[Composable] kotlin.Function0<kotlin.Unit>): kotlin.Int declared in p3.FooKt' type=kotlin.Int origin=null
+            content: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
+              FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
+                annotations:
+                  Composable
+                BLOCK_BODY
+                  CALL 'public final fun Greeting (name: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
+                    name: CONST String type=kotlin.String value="test"
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.kt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.kt
new file mode 100644
index 0000000..5a93532
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.kt
@@ -0,0 +1,40 @@
+// MODULE: compose
+// FILE: p2/bar.kt
+package p2;
+
+@MustBeDocumented
+@Retention(AnnotationRetention.BINARY)
+@Target(
+    AnnotationTarget.FUNCTION,
+    AnnotationTarget.TYPE,
+    AnnotationTarget.TYPE_PARAMETER,
+    AnnotationTarget.PROPERTY_GETTER
+)
+annotation class Composable
+// MODULE: lib(compose)
+// FILE: p3/foo.kt
+package p3;
+
+import p2.Composable
+
+fun setContent(content: @Composable () -> Unit): Int {
+    content()
+    return 3
+}
+// MODULE: main(lib, compose)
+// FILE: main.kt
+import p2.Composable
+import p3.setContent
+
+fun test(): Int {
+    return setContent {
+        Greeting("test")
+    }
+}
+
+@Composable
+fun Greeting(name: String) {
+    show("hi $name!")
+}
+
+fun show(str: String) {}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.txt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.txt
new file mode 100644
index 0000000..1046687
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation.txt
@@ -0,0 +1,18 @@
+final class MainKt$test$1 {
+    // source: 'main.kt'
+    enclosing method MainKt.test()I
+    public final static field INSTANCE: MainKt$test$1
+    inner (anonymous) class MainKt$test$1
+    static method <clinit>(): void
+    method <init>(): void
+    public synthetic bridge method invoke(): java.lang.Object
+    public final method invoke(): void
+}
+
+public final class MainKt {
+    // source: 'main.kt'
+    inner (anonymous) class MainKt$test$1
+    public final static method Greeting(p0: java.lang.String): void
+    public final static method show(p0: java.lang.String): void
+    public final static method test(): int
+}
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.ir.txt
new file mode 100644
index 0000000..f3b8345
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.ir.txt
@@ -0,0 +1,14 @@
+MODULE_FRAGMENT
+  FILE fqName:<root> fileName:main.kt
+    FUN name:Bar visibility:public modality:FINAL <> () returnType:kotlin.Unit
+      annotations:
+        Composable
+      BLOCK_BODY
+        CALL 'public final fun Foo (text: @[Composable] kotlin.Function0<kotlin.Unit>): kotlin.Unit declared in p3.FooKt' type=kotlin.Unit origin=null
+          text: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
+            FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
+              annotations:
+                Composable
+              BLOCK_BODY
+                RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.Bar'
+                  GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.kt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.kt
new file mode 100644
index 0000000..4c8fe0a
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.kt
@@ -0,0 +1,34 @@
+// MODULE: compose
+// FILE: p2/bar.kt
+package p2;
+
+@MustBeDocumented
+@Retention(AnnotationRetention.BINARY)
+@Target(
+    AnnotationTarget.FUNCTION,
+    AnnotationTarget.TYPE,
+    AnnotationTarget.TYPE_PARAMETER,
+    AnnotationTarget.PROPERTY_GETTER
+)
+annotation class Composable
+// MODULE: lib(compose)
+// FILE: p3/foo.kt
+package p3;
+
+import p2.Composable
+
+@Composable
+public fun Foo(
+    text: @Composable () -> Unit,
+) {}
+// MODULE: main(lib, compose)
+// FILE: main.kt
+import p2.Composable
+import p3.Foo
+
+@Composable
+public fun Bar() {
+    Foo(
+        text = {}, // @Composable invocations can only happen from the context of a @Composable function
+    )
+}
\ No newline at end of file
diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.txt b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.txt
new file mode 100644
index 0000000..b4464de
--- /dev/null
+++ b/analysis/analysis-api/testData/components/compilerFacility/compilationMultiModule/lambdaParameterWithAnnotation2.txt
@@ -0,0 +1,16 @@
+final class MainKt$Bar$1 {
+    // source: 'main.kt'
+    enclosing method MainKt.Bar()V
+    public final static field INSTANCE: MainKt$Bar$1
+    inner (anonymous) class MainKt$Bar$1
+    static method <clinit>(): void
+    method <init>(): void
+    public synthetic bridge method invoke(): java.lang.Object
+    public final method invoke(): void
+}
+
+public final class MainKt {
+    // source: 'main.kt'
+    inner (anonymous) class MainKt$Bar$1
+    public final static method Bar(): void
+}
diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt
index d9ffc51..94b682e 100644
--- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt
+++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt
@@ -44,10 +44,7 @@
 import org.jetbrains.kotlin.ir.expressions.impl.*
 import org.jetbrains.kotlin.ir.symbols.*
 import org.jetbrains.kotlin.ir.types.*
-import org.jetbrains.kotlin.ir.util.dump
-import org.jetbrains.kotlin.ir.util.isPrimitiveArray
-import org.jetbrains.kotlin.ir.util.isUnsignedArray
-import org.jetbrains.kotlin.ir.util.render
+import org.jetbrains.kotlin.ir.util.*
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType
 import org.jetbrains.kotlin.types.Variance
@@ -1065,6 +1062,7 @@
         // See KT-62598 and its fix for details.
         val expectedType = unsubstitutedParameterType.takeIf { visitor.annotationMode && unsubstitutedParameterType?.isArrayType == true }
         var irArgument = visitor.convertToIrExpression(argument, expectedType = expectedType)
+        irArgument.attachAnnotationsFromReturnTypeIfNeeded(parameter?.returnTypeRef)
         if (unsubstitutedParameterType != null) {
             with(visitor.implicitCastInserter) {
                 val argumentType = argument.resolvedType.fullyExpandedType(session)
@@ -1111,6 +1109,11 @@
         return this
     }
 
+    private fun IrExpression.attachAnnotationsFromReturnTypeIfNeeded(firTypeRef: FirTypeRef?) {
+        if (firTypeRef == null || this !is IrFunctionExpression) return
+        function.copyAnnotationsFrom(firTypeRef.toIrType())
+    }
+
     private fun IrExpression.applyImplicitIntegerCoercionIfNeeded(
         argument: FirExpression,
         parameter: FirValueParameter?,