GROOVY-11479: STC: closure or lambda parameter type must remain mutable

do not use the type from the SAM directory
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java
index 4292491..ceb280c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/AbstractFunctionalInterfaceWriter.java
@@ -33,6 +33,7 @@
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.ast.ClassHelper.isDynamicTyped;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.hasUnresolvedGenerics;
 import static org.codehaus.groovy.classgen.asm.BytecodeHelper.getClassInternalName;
 import static org.codehaus.groovy.classgen.asm.BytecodeHelper.getMethodDescriptor;
 
@@ -113,12 +114,14 @@
             throw new RuntimeParserException("The inferred type[" + inferredType.redirect() + "] is not compatible with the parameter type[" + parameterType.redirect() + "]", parameterType);
         }
 
-        ClassNode type = inferredType;
+        ClassNode type;
         if (isPrimitiveType(parameterType)) {
             if (!isPrimitiveType(inferredType)) {
                 // The non-primitive type and primitive type are not allowed to mix since Java 9+
                 // java.lang.invoke.LambdaConversionException: Type mismatch for instantiated parameter 0: class java.lang.Integer is not a subtype of int
-                type = getUnwrapper(inferredType);
+                type = getUnwrapper(inferredType).getPlainNodeReference(false);
+            } else {
+                type = inferredType.getPlainNodeReference(false);
             }
         } else if (isPrimitiveType(inferredType)) {
             // GROOVY-9790: bootstrap method initialization exception raised when lambda parameter type is wrong
@@ -128,11 +131,21 @@
                     && (parameterType.equals(getUnwrapper(parameterType)) || inferredType.equals(getWrapper(inferredType)))) { // (2)
                 // The non-primitive type and primitive type are not allowed to mix since Java 9+
                 // java.lang.invoke.LambdaConversionException: Type mismatch for instantiated parameter 0: int is not a subtype of class java.lang.Object
-                type = getWrapper(inferredType);
+                type = getWrapper(inferredType).getPlainNodeReference();
+            } else {
+                type = inferredType.getPlainNodeReference(false);
             }
-        }
-        if (type.isGenericsPlaceHolder()) {
-            type = type.redirect();
+        } else {
+            type = inferredType;
+            // GROOVY-11304: no placeholders
+            if (hasUnresolvedGenerics(type)) type = type.redirect();
+            // GROOVY-11479: mutable for node metadata or type annotations
+            if (type.toString(false).equals(parameterType.toString(false))) {
+                type = parameterType;
+            } else {
+                // TODO: deep copy if type args set
+                type = type.getPlainNodeReference();
+            }
         }
         return type;
     }
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index db5446a..1fbaef6 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1035,7 +1035,10 @@
             for (int i = 0; i < n; i += 1) {
                 Parameter parameter = closureParameters[i];
                 if (parameter.isDynamicTyped()) {
-                    parameter.setType(expectedTypes[i]); // GROOVY-11083, GROOVY-11085, et al.
+                    ClassNode type = expectedTypes[i].getPlainNodeReference(false); // GROOVY-11479
+                    if (!expectedTypes[i].isGenericsPlaceHolder())
+                        type.setGenericsTypes(expectedTypes[i].getGenericsTypes());
+                    parameter.setType(type); // GROOVY-11083, GROOVY-11085, et al.
                 } else {
                     checkParamType(parameter, expectedTypes[i], i == n-1, rhsExpression instanceof LambdaExpression);
                 }
diff --git a/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
index 74746e3..d8758d9 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/TypeAnnotationsTest.groovy
@@ -257,6 +257,42 @@
         ])
     }
 
+    // GROOVY-11479
+    void testTypeAnnotationsForClosure() {
+        def bytecode = compile(classNamePattern: 'Foo\\$_closure1', method: 'doCall', imports + '''
+            @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno0 { }
+            @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno1 { }
+
+            @groovy.transform.CompileStatic
+            class Foo {
+                @TypeAnno0 java.util.function.IntUnaryOperator bar = { @TypeAnno1 def i -> 1 }
+            }
+        ''')
+        assert bytecode.hasStrictSequence([
+                'public doCall(I)Ljava/lang/Integer;',
+                '@LTypeAnno1;() : METHOD_FORMAL_PARAMETER 0, null',
+                'L0'
+        ])
+    }
+
+    // GROOVY-11479
+    void testTypeAnnotationsForLambda() {
+        def bytecode = compile(classNamePattern: 'Foo\\$_lambda1', method: 'doCall', imports + '''
+            @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno0 { }
+            @Retention(RUNTIME) @Target(TYPE_USE) @interface TypeAnno1 { }
+
+            @groovy.transform.CompileStatic
+            class Foo {
+                @TypeAnno0 java.util.function.IntUnaryOperator bar = (@TypeAnno1 int i) -> 1
+            }
+        ''')
+        assert bytecode.hasStrictSequence([
+                'public doCall(I)I',
+                '@LTypeAnno1;() : METHOD_FORMAL_PARAMETER 0, null',
+                'L0'
+        ])
+    }
+
     void testTypeAnnotationsForField1() {
         def bytecode = compile(classNamePattern: 'Foo', field: 'foo', imports + '''
             @Retention(RUNTIME) @Target(FIELD) @interface FieldAnno { String value() }