You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/01/01 00:12:19 UTC

[groovy] branch GROOVY_4_0_X updated (7c4bc91 -> d4351c2)

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

paulk pushed a change to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from 7c4bc91  GROOVY-10435: Bump log4j2 version to 2.17.1 (test dependency)
     new cc45b74  Bump year and "updateNotices"
     new d4351c2  GROOVY-6603: STC: check closure calls in methods with parameter metadata

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 NOTICE                                             |  2 +-
 .../groovy/org.apache.groovy-documented.gradle     |  4 +-
 notices/NOTICE-BASE                                |  2 +-
 notices/NOTICE-BINZIP                              |  2 +-
 notices/NOTICE-GROOID                              |  2 +-
 notices/NOTICE-GROOIDJARJAR                        |  2 +-
 notices/NOTICE-JARJAR                              |  2 +-
 notices/NOTICE-SDK                                 |  2 +-
 .../ast/builder/AstSpecificationCompiler.groovy    |  4 +-
 .../groovy/transform/stc/ClosureSignatureHint.java | 43 +++++++++---
 src/main/java/groovy/transform/stc/SimpleType.java | 13 ++--
 .../transform/stc/StaticTypeCheckingVisitor.java   | 81 +++++++++++++---------
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 31 +++++----
 subprojects/groovy-console/NOTICE                  |  2 +-
 .../groovy-sql/src/main/java/groovy/sql/Sql.java   | 11 +--
 15 files changed, 125 insertions(+), 78 deletions(-)

[groovy] 01/02: Bump year and "updateNotices"

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit cc45b74ceb82ef48047fbe6ea55d0aaeaac09eae
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sat Jan 1 10:08:41 2022 +1000

    Bump year and "updateNotices"
---
 NOTICE                                                       | 2 +-
 buildSrc/src/main/groovy/org.apache.groovy-documented.gradle | 4 ++--
 notices/NOTICE-BASE                                          | 2 +-
 notices/NOTICE-BINZIP                                        | 2 +-
 notices/NOTICE-GROOID                                        | 2 +-
 notices/NOTICE-GROOIDJARJAR                                  | 2 +-
 notices/NOTICE-JARJAR                                        | 2 +-
 notices/NOTICE-SDK                                           | 2 +-
 subprojects/groovy-console/NOTICE                            | 2 +-
 9 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/NOTICE b/NOTICE
index f2f6823..1a6789b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/buildSrc/src/main/groovy/org.apache.groovy-documented.gradle b/buildSrc/src/main/groovy/org.apache.groovy-documented.gradle
index 49134e7..6e3b5e2 100644
--- a/buildSrc/src/main/groovy/org.apache.groovy-documented.gradle
+++ b/buildSrc/src/main/groovy/org.apache.groovy-documented.gradle
@@ -56,7 +56,7 @@ tasks.withType(Javadoc).configureEach {
         encoding = 'UTF-8'
         version = true
         overview = project.relativePath(rootProject.file('src/main/java/overviewj.html'))
-        bottom = 'Copyright &copy; 2003-2021 The Apache Software Foundation. All rights reserved.'
+        bottom = 'Copyright &copy; 2003-2022 The Apache Software Foundation. All rights reserved.'
         source = sharedConfiguration.targetJavaVersion.get()
         links('https://docs.oracle.com/javase/8/docs/api/',
                 'https://docs.oracle.com/javaee/7/api/',
@@ -75,7 +75,7 @@ tasks.withType(Groovydoc).configureEach {
     windowTitle = "Groovy ${versions.groovy}"
     docTitle = "Groovy ${versions.groovy}"
     header = "Groovy ${versions.groovy}"
-    footer = 'Copyright &copy; 2003-2021 The Apache Software Foundation. All rights reserved.'
+    footer = 'Copyright &copy; 2003-2022 The Apache Software Foundation. All rights reserved.'
     overviewText = rootProject.resources.text.fromFile('src/main/java/overview.html')
     includePrivate = false
     link 'https://docs.oracle.com/javaee/7/api/', 'javax.servlet.', 'javax.management.'
diff --git a/notices/NOTICE-BASE b/notices/NOTICE-BASE
index 45845c1..68e0f2d 100644
--- a/notices/NOTICE-BASE
+++ b/notices/NOTICE-BASE
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/notices/NOTICE-BINZIP b/notices/NOTICE-BINZIP
index 1baea31..89ab35e 100644
--- a/notices/NOTICE-BINZIP
+++ b/notices/NOTICE-BINZIP
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/notices/NOTICE-GROOID b/notices/NOTICE-GROOID
index c5f997f..b6423fb 100644
--- a/notices/NOTICE-GROOID
+++ b/notices/NOTICE-GROOID
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/notices/NOTICE-GROOIDJARJAR b/notices/NOTICE-GROOIDJARJAR
index d87cb10..694516d 100644
--- a/notices/NOTICE-GROOIDJARJAR
+++ b/notices/NOTICE-GROOIDJARJAR
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/notices/NOTICE-JARJAR b/notices/NOTICE-JARJAR
index d686b4d..2111cdc 100644
--- a/notices/NOTICE-JARJAR
+++ b/notices/NOTICE-JARJAR
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/notices/NOTICE-SDK b/notices/NOTICE-SDK
index 7c4081e..df0585c 100644
--- a/notices/NOTICE-SDK
+++ b/notices/NOTICE-SDK
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/subprojects/groovy-console/NOTICE b/subprojects/groovy-console/NOTICE
index 5de6dc3..e25e1ec 100644
--- a/subprojects/groovy-console/NOTICE
+++ b/subprojects/groovy-console/NOTICE
@@ -1,5 +1,5 @@
 Apache Groovy
-Copyright 2003-2021 The Apache Software Foundation
+Copyright 2003-2022 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).

[groovy] 02/02: GROOVY-6603: STC: check closure calls in methods with parameter metadata

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d4351c21dc2ad3b52e42abe6d07f05c91419427b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Dec 27 13:31:12 2021 -0600

    GROOVY-6603: STC: check closure calls in methods with parameter metadata
    
    - warn that `SimpleType` cannot handle type with generics
---
 .../ast/builder/AstSpecificationCompiler.groovy    |  4 +-
 .../groovy/transform/stc/ClosureSignatureHint.java | 43 +++++++++---
 src/main/java/groovy/transform/stc/SimpleType.java | 13 ++--
 .../transform/stc/StaticTypeCheckingVisitor.java   | 81 +++++++++++++---------
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 31 +++++----
 .../groovy-sql/src/main/java/groovy/sql/Sql.java   | 11 +--
 6 files changed, 115 insertions(+), 68 deletions(-)

diff --git a/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy b/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
index 5018803..fb60d81 100644
--- a/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
+++ b/src/main/groovy/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy
@@ -20,7 +20,7 @@ package org.codehaus.groovy.ast.builder
 
 import groovy.transform.CompileStatic
 import groovy.transform.stc.ClosureParams
-import groovy.transform.stc.SimpleType
+import groovy.transform.stc.FromString
 import org.codehaus.groovy.ast.ASTNode
 import org.codehaus.groovy.ast.AnnotationNode
 import org.codehaus.groovy.ast.ClassHelper
@@ -167,7 +167,7 @@ class AstSpecificationCompiler implements GroovyInterceptable {
      */
     @CompileStatic
     private void captureAndCreateNode(String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock,
-            @ClosureParams(value=SimpleType, options="java.util.List<org.codehaus.groovy.ast.ASTNode>") Closure ctorBlock) {
+            @ClosureParams(value=FromString, options="java.util.List<org.codehaus.groovy.ast.ASTNode>") Closure ctorBlock) {
         if (!argBlock) throw new IllegalArgumentException("nodes of type $name require arguments to be specified")
 
         def oldProps = new ArrayList<>(expression)
diff --git a/src/main/java/groovy/transform/stc/ClosureSignatureHint.java b/src/main/java/groovy/transform/stc/ClosureSignatureHint.java
index ce36a03..9bf986b 100644
--- a/src/main/java/groovy/transform/stc/ClosureSignatureHint.java
+++ b/src/main/java/groovy/transform/stc/ClosureSignatureHint.java
@@ -26,6 +26,7 @@ import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.messages.WarningMessage;
 
 import java.util.List;
 
@@ -58,7 +59,7 @@ public abstract class ClosureSignatureHint {
      * @param gtIndex the index of the generic type to extract
      * @return the n-th generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
      */
-    public static ClassNode pickGenericType(ClassNode type, int gtIndex) {
+    public static ClassNode pickGenericType(final ClassNode type, final int gtIndex) {
         final GenericsType[] genericsTypes = type.getGenericsTypes();
         if (genericsTypes==null || genericsTypes.length<gtIndex) {
             return ClassHelper.OBJECT_TYPE;
@@ -73,7 +74,7 @@ public abstract class ClosureSignatureHint {
      * @param gtIndex the index of the generic type to extract
      * @return the generic type, or {@link org.codehaus.groovy.ast.ClassHelper#OBJECT_TYPE} if it doesn't exist.
      */
-    public static ClassNode pickGenericType(MethodNode node, int parameterIndex, int gtIndex) {
+    public static ClassNode pickGenericType(final MethodNode node, final int parameterIndex, final int gtIndex) {
         final Parameter[] parameters = node.getParameters();
         final ClassNode type = parameters[parameterIndex].getOriginType();
         return pickGenericType(type, gtIndex);
@@ -120,24 +121,46 @@ public abstract class ClosureSignatureHint {
     public abstract List<ClassNode[]> getClosureSignatures(MethodNode node, SourceUnit sourceUnit, CompilationUnit compilationUnit, String[] options, ASTNode usage);
 
     /**
-     * Finds a class node given a string representing the type. Performs a lookup in the compilation unit to check if it is done in the same source unit.
+     * Produces a {@link ClassNode} given a string representing the type. Checks
+     * the supplied compilation unit in case it is also being compiled.
+     *
      * @param sourceUnit source unit
      * @param compilationUnit compilation unit
-     * @param className the name of the class we want to get a {@link org.codehaus.groovy.ast.ClassNode} for
-     * @return a ClassNode representing the type
+     * @param className the type name to resolve
      */
-    protected ClassNode findClassNode(final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final String className) {
+    protected ClassNode findClassNode(final SourceUnit sourceUnit, final CompilationUnit compilationUnit, String className) {
         if (className.endsWith("[]")) {
             return findClassNode(sourceUnit, compilationUnit, className.substring(0, className.length() - 2)).makeArray();
         }
+        int i = className.indexOf('<');
+        if (i > 0) {
+            className = className.substring(0, i);
+            String message = getClass().getSimpleName() + " doesn't support generics";
+            sourceUnit.getErrorCollector().addWarning(WarningMessage.LIKELY_ERRORS, message,
+                    null, null); // TODO: include reference to the source method & parameter
+        }
+
         ClassNode cn = compilationUnit.getClassNode(className);
         if (cn == null) {
-            try {
-                cn = ClassHelper.make(Class.forName(className, false, sourceUnit.getClassLoader()));
-            } catch (ClassNotFoundException e) {
-                cn = ClassHelper.make(className);
+            cn = ClassHelper.make(className);
+            if (!ClassHelper.isCachedType(cn)) {
+                Class<?> c = tryLoadClass(className, sourceUnit.getClassLoader());
+                if (c != null) {
+                    cn = ClassHelper.make(c);
+                }
+            }
+            if (cn.getGenericsTypes() != null) {
+                cn = cn.getPlainNodeReference();
             }
         }
         return cn;
     }
+
+    private static Class<?> tryLoadClass(final String className, final ClassLoader classLoader) {
+        try {
+            return Class.forName(className, false, classLoader);
+        } catch (ClassNotFoundException ignore) {
+            return null;
+        }
+    }
 }
diff --git a/src/main/java/groovy/transform/stc/SimpleType.java b/src/main/java/groovy/transform/stc/SimpleType.java
index 8866e3b..5d7a1cb 100644
--- a/src/main/java/groovy/transform/stc/SimpleType.java
+++ b/src/main/java/groovy/transform/stc/SimpleType.java
@@ -24,13 +24,12 @@ import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
 
+import static java.util.Arrays.stream;
+
 public class SimpleType extends SingleSignatureClosureHint {
+
     @Override
-    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit unit, final ASTNode usage) {
-        ClassNode[] result = new ClassNode[options.length];
-        for (int i = 0; i < result.length; i++) {
-            result[i] = findClassNode(sourceUnit, unit, options[i]);
-        }
-        return result;
+    public ClassNode[] getParameterTypes(final MethodNode node, final String[] options, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final ASTNode usage) {
+        return stream(options).map(option -> findClassNode(sourceUnit, compilationUnit, option)).toArray(ClassNode[]::new);
     }
- }
+}
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 0d7fcf8..e42bf45 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2582,21 +2582,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     @Override
     protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
         typeCheckingContext.pushEnclosingMethod(node);
+        readClosureParameterAnnotation(node); // GROOVY-6603
         super.visitConstructorOrMethod(node, isConstructor);
         if (node.hasDefaultValue()) {
-            for (Parameter parameter : node.getParameters()) {
-                if (!parameter.hasInitialExpression()) continue;
-                // GROOVY-10094: visit param default argument expression
-                visitInitialExpression(parameter.getInitialExpression(), varX(parameter), parameter);
-                // GROOVY-10104: remove direct target setting to prevent errors
-                parameter.getInitialExpression().visit(new CodeVisitorSupport() {
-                    @Override
-                    public void visitMethodCallExpression(final MethodCallExpression mce) {
-                        super.visitMethodCallExpression(mce);
-                        mce.setMethodTarget(null);
-                    }
-                });
-            }
+            visitDefaultParameterArguments(node.getParameters());
         }
         if (!isConstructor) {
             returnAdder.visitMethod(node); // GROOVY-7753: we cannot count these auto-generated return statements, see `typeCheckingContext.pushEnclosingReturnStatement`
@@ -2604,6 +2593,38 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         typeCheckingContext.popEnclosingMethod();
     }
 
+    private void readClosureParameterAnnotation(final MethodNode node) {
+        for (Parameter parameter : node.getParameters()) {
+            for (AnnotationNode annotation : parameter.getAnnotations()) {
+                if (annotation.getClassNode().equals(CLOSUREPARAMS_CLASSNODE)) {
+                    // GROOVY-6603: propagate closure parameter types
+                    Expression value = annotation.getMember("value");
+                    Expression options = annotation.getMember("options");
+                    List<ClassNode[]> signatures = getSignaturesFromHint(node, value, options, annotation);
+                    if (signatures.size() == 1) { // TODO: handle multiple signatures
+                        parameter.putNodeMetaData(CLOSURE_ARGUMENTS, Arrays.stream(signatures.get(0)).map(t -> new Parameter(t,"")).toArray(Parameter[]::new));
+                    }
+                }
+            }
+        }
+    }
+
+    private void visitDefaultParameterArguments(final Parameter[] parameters) {
+        for (Parameter parameter : parameters) {
+            if (!parameter.hasInitialExpression()) continue;
+            // GROOVY-10094: visit param default argument expression
+            visitInitialExpression(parameter.getInitialExpression(), varX(parameter), parameter);
+            // GROOVY-10104: remove direct target setting to prevent errors
+            parameter.getInitialExpression().visit(new CodeVisitorSupport() {
+                @Override
+                public void visitMethodCallExpression(final MethodCallExpression mce) {
+                    super.visitMethodCallExpression(mce);
+                    mce.setMethodTarget(null);
+                }
+            });
+        }
+    }
+
     @Override
     protected void visitObjectInitializerStatements(final ClassNode node) {
         // GROOVY-5450: create fake constructor node so final field analysis can allow write within non-static initializer block(s)
@@ -2883,12 +2904,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         List<AnnotationNode> annotations = target.getAnnotations(CLOSUREPARAMS_CLASSNODE);
         if (annotations != null && !annotations.isEmpty()) {
             for (AnnotationNode annotation : annotations) {
-                Expression hintClass = annotation.getMember("value");
-                if (hintClass instanceof ClassExpression) {
-                    Expression options = annotation.getMember("options");
-                    Expression resolverClass = annotation.getMember("conflictResolutionStrategy");
-                    doInferClosureParameterTypes(receiver, arguments, expression, method, hintClass, resolverClass, options);
-                }
+                Expression value = annotation.getMember("value");
+                Expression options = annotation.getMember("options");
+                Expression conflictResolver = annotation.getMember("conflictResolutionStrategy");
+                doInferClosureParameterTypes(receiver, arguments, expression, method, value, conflictResolver, options);
             }
         } else if (isSAMType(target.getOriginType())) { // SAM-type coercion
             Map<GenericsTypeName, GenericsType> context = extractPlaceHoldersVisibleToDeclaration(receiver, method, arguments);
@@ -2961,23 +2980,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private List<ClassNode[]> getSignaturesFromHint(final ClosureExpression expression, final MethodNode selectedMethod, final Expression hintClass, final Expression options) {
-        // initialize hints
-        List<ClassNode[]> closureSignatures;
+    private List<ClassNode[]> getSignaturesFromHint(final MethodNode mn, final Expression hintType, final Expression options, final ASTNode usage) {
+        String hintTypeName = hintType.getText(); // load hint class using compiler's classloader
         try {
-            ClassLoader transformLoader = getTransformLoader();
             @SuppressWarnings("unchecked")
-            Class<? extends ClosureSignatureHint> hint = (Class<? extends ClosureSignatureHint>) transformLoader.loadClass(hintClass.getText());
-            ClosureSignatureHint hintInstance = hint.getDeclaredConstructor().newInstance();
-            closureSignatures = hintInstance.getClosureSignatures(
-                    selectedMethod instanceof ExtensionMethodNode ? ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode() : selectedMethod,
+            Class<? extends ClosureSignatureHint> hintClass = (Class<? extends ClosureSignatureHint>) getTransformLoader().loadClass(hintTypeName);
+            List<ClassNode[]> closureSignatures = hintClass.getDeclaredConstructor().newInstance().getClosureSignatures(
+                    mn instanceof ExtensionMethodNode ? ((ExtensionMethodNode) mn).getExtensionMethodNode() : mn,
                     typeCheckingContext.getSource(),
                     typeCheckingContext.getCompilationUnit(),
-                    convertToStringArray(options), expression);
-        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
+                    convertToStringArray(options),
+                    usage);
+            return closureSignatures;
+        } catch (ReflectiveOperationException e) {
             throw new GroovyBugError(e);
         }
-        return closureSignatures;
     }
 
     private List<ClassNode[]> resolveWithResolver(final List<ClassNode[]> candidates, final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression resolverClass, final Expression options) {
@@ -3009,7 +3026,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         Parameter[] closureParams = expression.getParameters();
         if (closureParams == null) return; // no-arg closure
 
-        List<ClassNode[]> closureSignatures = getSignaturesFromHint(expression, selectedMethod, hintClass, options);
+        List<ClassNode[]> closureSignatures = getSignaturesFromHint(selectedMethod, hintClass, options, expression);
         List<ClassNode[]> candidates = new LinkedList<>();
         for (ClassNode[] signature : closureSignatures) {
             // in order to compute the inferred types of the closure parameters, we're using the following trick:
@@ -3356,7 +3373,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         if (parameters != null) {
                             typeCheckClosureCall(callArguments, args, parameters);
                         }
-                        ClassNode type = getType(((ASTNode) variable));
+                        ClassNode type = getType((ASTNode) variable);
                         if (type.equals(CLOSURE_TYPE)) { // GROOVY-10098, et al.
                             GenericsType[] genericsTypes = type.getGenericsTypes();
                             if (genericsTypes != null && genericsTypes.length == 1
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index bf2e779..8d2039b 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -1223,25 +1223,34 @@ assert result == ['b', 'r', 'e', 'a', 'd', 'b', 'u', 't', 't', 'e', 'r']
     }
 
     void testGroovy6602() {
-        shouldFailWithMessages '''import groovy.transform.stc.FromString
-            void foo(@ClosureParams(value=FromString, options="java.lang.Number") Closure cl) {
-                cl.call(4.5)
+        shouldFailWithMessages '''import groovy.transform.stc.SimpleType
+            void foo(@ClosureParams(value=SimpleType, options="java.lang.Number") Closure c) {
+                c.call(4.5)
             }
             foo { Integer i -> println i }
         ''',
         'Expected type java.lang.Number for closure parameter: i'
     }
 
+    void testGroovy6603() {
+        shouldFailWithMessages '''import groovy.transform.stc.SimpleType
+            void foo(@ClosureParams(value=SimpleType, options="java.lang.Number") Closure c) {
+                c.call("x")
+            }
+        ''',
+        'Cannot call closure that accepts [java.lang.Number] with [java.lang.String]'
+    }
+
     void testGroovy6729() {
         assertScript '''import groovy.transform.stc.FirstParam
-            static <T> List<T> callee01(List<T>self, @ClosureParams(FirstParam.FirstGenericType) Closure c) {
-                self.each {
+            static <T> List<T> foo(List<T> list, @ClosureParams(FirstParam.FirstGenericType) Closure c) {
+                list.each {
                     c.call(it)
                 }
-                return self
+                return list
             }
-            callee01(["a","b","c"]) { a ->
-                println(a.toUpperCase()) // [Static type checking] - Cannot find matching method java.lang.Object#toUpperCase(). Please check if the declared type is correct and if the method exists.
+            foo(["a","b","c"]) { s ->
+                s.toUpperCase() // Cannot find matching method java.lang.Object#toUpperCase()
             }
         '''
     }
@@ -1304,11 +1313,9 @@ assert result == ['b', 'r', 'e', 'a', 'd', 'b', 'u', 't', 't', 'e', 'r']
     }
 
     void testGroovy9518b() {
-        assertScript '''
-            import groovy.transform.stc.SimpleType
-
+        assertScript '''import groovy.transform.stc.FromString
             class C {
-                C(String s, @ClosureParams(value=SimpleType, options='java.util.List') Closure<Integer> c) {
+                C(String s, @ClosureParams(value=FromString,options="java.util.List<java.lang.Integer>") Closure<Integer> c) {
                 }
             }
 
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
index 5186bef..92c602b 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
@@ -24,6 +24,7 @@ import groovy.lang.MissingPropertyException;
 import groovy.lang.Tuple;
 import groovy.transform.NamedParam;
 import groovy.transform.stc.ClosureParams;
+import groovy.transform.stc.FromString;
 import groovy.transform.stc.SimpleType;
 import org.codehaus.groovy.runtime.InvokerHelper;
 import org.codehaus.groovy.vmplugin.VMPluginFactory;
@@ -2398,7 +2399,7 @@ public class Sql implements AutoCloseable {
      * @throws SQLException if a database access error occurs
      * @since 2.3.2
      */
-    public void execute(String sql, @ClosureParams(value=SimpleType.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
+    public void execute(String sql, @ClosureParams(value=FromString.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
         Connection connection = createConnection();
         Statement statement = null;
         try {
@@ -2485,7 +2486,7 @@ public class Sql implements AutoCloseable {
      * @see #execute(String, Closure)
      * @since 2.3.2
      */
-    public void execute(String sql, List<Object> params, @ClosureParams(value=SimpleType.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
+    public void execute(String sql, List<Object> params, @ClosureParams(value=FromString.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
         Connection connection = createConnection();
         PreparedStatement statement = null;
         try {
@@ -2542,7 +2543,7 @@ public class Sql implements AutoCloseable {
      * @throws SQLException if a database access error occurs
      * @since 2.3.2
      */
-    public void execute(Map params, String sql, @ClosureParams(value=SimpleType.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
+    public void execute(Map params, String sql, @ClosureParams(value=FromString.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
         execute(sql, singletonList(params), processResults);
     }
 
@@ -2582,7 +2583,7 @@ public class Sql implements AutoCloseable {
      * @see #execute(String, List, Closure)
      * @since 2.3.2
      */
-    public void execute(String sql, Object[] params, @ClosureParams(value=SimpleType.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
+    public void execute(String sql, Object[] params, @ClosureParams(value=FromString.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
         execute(sql, Arrays.asList(params), processResults);
     }
 
@@ -2628,7 +2629,7 @@ public class Sql implements AutoCloseable {
      * @see #execute(String, List, Closure)
      * @since 2.3.2
      */
-    public void execute(GString gstring, @ClosureParams(value=SimpleType.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
+    public void execute(GString gstring, @ClosureParams(value=FromString.class, options={"boolean,java.util.List<groovy.sql.GroovyRowResult>", "boolean,int"}) Closure processResults) throws SQLException {
         List<Object> params = getParameters(gstring);
         String sql = asSql(gstring, params);
         execute(sql, params, processResults);