You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/10/29 04:58:25 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-9790: bootstrap method initialization exception raised when lambda parameter type is wrong

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 5591f06  GROOVY-9790: bootstrap method initialization exception raised when lambda parameter type is wrong
5591f06 is described below

commit 5591f06ce135484ff55fe9249e18428b54290467
Author: Daniel Sun <su...@apache.org>
AuthorDate: Fri Oct 23 17:37:13 2020 +0800

    GROOVY-9790: bootstrap method initialization exception raised when lambda parameter type is wrong
    
    (cherry picked from commit d7357882f116a2e18daba6d64a66220f7a2c6327)
---
 .../asm/sc/AbstractFunctionalInterfaceWriter.java  | 20 ++++--
 src/test/groovy/bugs/Groovy9790.groovy             | 72 ++++++++++++++++++++++
 2 files changed, 88 insertions(+), 4 deletions(-)

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 e425cc0..57c681c 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
@@ -24,6 +24,7 @@ import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
+import org.codehaus.groovy.syntax.RuntimeParserException;
 import org.objectweb.asm.Handle;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
@@ -32,6 +33,7 @@ import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
+import static org.codehaus.groovy.ast.ClassHelper.getUnwrapper;
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_FUNCTIONAL_INTERFACE_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PARAMETER_TYPE;
@@ -106,17 +108,27 @@ public interface AbstractFunctionalInterfaceWriter {
     }
 
     default ClassNode convertParameterType(ClassNode parameterType, ClassNode inferredType) {
+        if (!getWrapper(inferredType.redirect()).isDerivedFrom(getWrapper(parameterType.redirect()))) {
+            throw new RuntimeParserException("The inferred type[" + inferredType.redirect() + "] is not compatible with the parameter type[" + parameterType.redirect() + "]", parameterType);
+        }
+
         ClassNode type;
         boolean isParameterTypePrimitive = ClassHelper.isPrimitiveType(parameterType);
         boolean isInferredTypePrimitive = ClassHelper.isPrimitiveType(inferredType);
         if (!isParameterTypePrimitive && isInferredTypePrimitive) {
-            // 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);
+            if (parameterType != getUnwrapper(parameterType) && inferredType != getWrapper(inferredType)) {
+                // GROOVY-9790: bootstrap method initialization exception raised when lambda parameter type is wrong
+                // java.lang.BootstrapMethodError: bootstrap method initialization exception
+                type = inferredType;
+            } else {
+                // 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);
+            }
         } else if (isParameterTypePrimitive && !isInferredTypePrimitive) {
             // 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 = ClassHelper.getUnwrapper(inferredType);
+            type = getUnwrapper(inferredType);
         } else {
             type = inferredType;
         }
diff --git a/src/test/groovy/bugs/Groovy9790.groovy b/src/test/groovy/bugs/Groovy9790.groovy
new file mode 100644
index 0000000..b2b4044
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9790.groovy
@@ -0,0 +1,72 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy9790 {
+    @Test
+    void "test GROOVY-9790 - 1"() {
+        assertScript '''
+            import java.util.stream.IntStream
+            
+            @groovy.transform.CompileStatic
+            def x() {
+                IntStream.range(0, 2).forEach((Integer i) -> { assert 0 <= i && i < 2})
+            }
+            
+            x()
+        '''
+    }
+
+    @Test
+    void "test GROOVY-9790 - 2"() {
+        assertScript '''
+            import java.util.stream.IntStream
+            
+            @groovy.transform.CompileStatic
+            def x() {
+                IntStream.range(0, 2).forEach((int i) -> { assert 0 <= i && i < 2})
+            }
+            
+            x()
+        '''
+    }
+
+    @Test
+    void "test GROOVY-9790 - 3"() {
+        def err = shouldFail '''
+            import java.util.stream.IntStream
+            
+            @groovy.transform.CompileStatic
+            def x() {
+                IntStream.range(0, 2).forEach((String i) -> { return i })
+            }
+            
+            x()
+        '''
+
+        assert err.toString().contains('The inferred type[int] is not compatible with the parameter type[java.lang.String]\n. At [6:48]')
+    }
+}