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

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

commit ccfd6053d1b52488577bcdb2ee4693b1cf907f10
Author: Eric Milles <[email protected]>
AuthorDate: Sun Mar 12 11:50:03 2023 -0500

    sync with `3_0_X`
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  22 +-
 .../classgen/asm/sc/StaticInvocationWriter.java    |  17 +-
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |   6 +-
 .../codehaus/groovy/control/CompilationUnit.java   |  19 +-
 .../codehaus/groovy/control/ProcessingUnit.java    |   4 +-
 .../codehaus/groovy/control/ResolveVisitor.java    |   2 +-
 .../transformers/BinaryExpressionTransformer.java  |   3 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 382 ++++++++++-----------
 .../transform/stc/StaticTypeCheckingVisitor.java   |   2 +-
 .../transform/trait/TraitASTTransformation.java    |   7 +-
 .../groovy/transform/stc/GenericsSTCTest.groovy    |  18 +-
 11 files changed, 235 insertions(+), 247 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java 
b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 8c4906dcb0..9d0d5409b9 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -402,28 +402,30 @@ public class GenericsUtils {
             newgTypes = new GenericsType[oldgTypes.length];
             for (int i = 0; i < newgTypes.length; i++) {
                 GenericsType oldgType = oldgTypes[i];
-                if (oldgType.isPlaceholder()) {
-                    if (genericsSpec.get(oldgType.getName()) != null) {
-                        newgTypes[i] = new 
GenericsType(genericsSpec.get(oldgType.getName()));
-                    } else {
-                        newgTypes[i] = new 
GenericsType(ClassHelper.OBJECT_TYPE);
-                    }
-                } else if (oldgType.isWildcard()) {
-                    ClassNode oldLower = oldgType.getLowerBound();
-                    ClassNode lower = oldLower != null ? 
correctToGenericsSpecRecurse(genericsSpec, oldLower, exclusions) : null;
+                if (oldgType.isWildcard()) {
                     ClassNode[] oldUpper = oldgType.getUpperBounds();
                     ClassNode[] upper = null;
                     if (oldUpper != null) {
+                        // correct "? extends T" or "? extends T & I"
                         upper = new ClassNode[oldUpper.length];
                         for (int j = 0; j < oldUpper.length; j++) {
                             upper[j] = 
correctToGenericsSpecRecurse(genericsSpec, oldUpper[j], exclusions);
                         }
                     }
+                    ClassNode oldLower = oldgType.getLowerBound();
+                    ClassNode lower = null;
+                    if (oldLower != null) {
+                        // correct "? super T"
+                        lower = correctToGenericsSpecRecurse(genericsSpec, 
oldLower, exclusions);
+                    }
                     GenericsType fixed = new GenericsType(oldgType.getType(), 
upper, lower);
-                    fixed.setName(oldgType.getName());
                     fixed.setWildcard(true);
                     newgTypes[i] = fixed;
+                } else if (oldgType.isPlaceholder()) {
+                    // correct "T"
+                    newgTypes[i] = new 
GenericsType(genericsSpec.getOrDefault(oldgType.getName(), 
ClassHelper.OBJECT_TYPE));
                 } else {
+                    // correct "List<T>", etc.
                     newgTypes[i] = new 
GenericsType(correctToGenericsSpecRecurse(genericsSpec, 
correctToGenericsSpec(genericsSpec, oldgType), exclusions));
                 }
             }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index af0b11f455..53aa8261db 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -22,6 +22,7 @@ import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.EnumConstantClassNode;
 import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.ast.InnerClassNode;
@@ -739,9 +740,9 @@ public class StaticInvocationWriter extends 
InvocationWriter {
                     controller.getOperandStack().doGroovyCast(type);
                 }
                 if 
(StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(topOperand, type)) 
return;
-                controller.getMethodVisitor().visitTypeInsn(CHECKCAST, 
type.isArray() ?
-                        BytecodeHelper.getTypeDescription(type) :
-                        BytecodeHelper.getClassInternalName(type.getName()));
+                controller.getMethodVisitor().visitTypeInsn(CHECKCAST, 
type.isArray()
+                        ? BytecodeHelper.getTypeDescription(type)
+                        : BytecodeHelper.getClassInternalName(type.getName()));
                 controller.getOperandStack().replace(type);
             }
         }
@@ -758,9 +759,11 @@ public class StaticInvocationWriter extends 
InvocationWriter {
                         type = ClassHelper.getWrapper(type);
                     }
                     ClassNode declaringClass = target.getDeclaringClass();
-                    if (type.getClass() != ClassNode.class
-                            && type.getClass() != InnerClassNode.class
-                            && type.getClass() != DecompiledClassNode.class) {
+                    Class<?>  typeClass = type.getClass();
+                    if (typeClass != ClassNode.class
+                            && typeClass != InnerClassNode.class
+                            && typeClass != DecompiledClassNode.class
+                            && typeClass != EnumConstantClassNode.class) {
                         type = declaringClass; // ex: LUB type
                     }
                     if (ClassHelper.OBJECT_TYPE.equals(declaringClass)) {
@@ -780,7 +783,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
     }
 
     @Override
-    protected boolean makeCachedCall(Expression origin, ClassExpression 
sender, Expression receiver, Expression message, Expression arguments, 
MethodCallerMultiAdapter adapter, boolean safe, boolean spreadSafe, boolean 
implicitThis, boolean containsSpreadExpression) {
+    protected boolean makeCachedCall(final Expression origin, final 
ClassExpression sender, final Expression receiver, final Expression message, 
final Expression arguments, final MethodCallerMultiAdapter adapter, final 
boolean safe, final boolean spreadSafe, final boolean implicitThis, final 
boolean containsSpreadExpression) {
         return false;
     }
 }
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 89ea087fb6..16e3033809 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -146,9 +146,7 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter implements Opcodes
             controller.getMethodVisitor().visitInsn(ARRAYLENGTH);
             controller.getOperandStack().replace(int_TYPE);
             return;
-        } else if (
-                (receiverType.implementsInterface(COLLECTION_TYPE)
-                        || COLLECTION_TYPE.equals(receiverType)) && 
("size".equals(propertyName) || "length".equals(propertyName))) {
+        } else if (("size".equals(propertyName) || 
"length".equals(propertyName)) && isOrImplements(receiverType, 
COLLECTION_TYPE)) {
             MethodCallExpression expr = new MethodCallExpression(
                     receiver,
                     "size",
@@ -164,7 +162,7 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter implements Opcodes
         boolean isStaticProperty = receiver instanceof ClassExpression
                 && (receiverType.isDerivedFrom(receiver.getType()) || 
receiverType.implementsInterface(receiver.getType()));
 
-        if (!isStaticProperty && (receiverType.implementsInterface(MAP_TYPE) 
|| MAP_TYPE.equals(receiverType))) {
+        if (!isStaticProperty && isOrImplements(receiverType, MAP_TYPE)) {
             // for maps, replace map.foo with map.get('foo')
             writeMapDotProperty(receiver, propertyName, safe);
             return;
diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java 
b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 7500ab1615..88aa216779 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -459,7 +459,7 @@ public class CompilationUnit extends ProcessingUnit {
      */
     public SourceUnit addSource(SourceUnit source) {
         String name = source.getName();
-        source.setClassLoader(this.classLoader);
+        source.setClassLoader(getClassLoader());
         for (SourceUnit su : queuedSources) {
             if (name.equals(su.getName())) return su;
         }
@@ -681,7 +681,6 @@ public class CompilationUnit extends ProcessingUnit {
                 resolveVisitor.setClassNodeResolver(classNodeResolver);
                 resolveVisitor.startResolving(node, source);
             }
-
         }
     };
 
@@ -697,11 +696,11 @@ public class CompilationUnit extends ProcessingUnit {
     private final SourceUnitOperation convert = new SourceUnitOperation() {
         public void call(SourceUnit source) throws CompilationFailedException {
             source.convert();
-            CompilationUnit.this.ast.addModule(source.getAST());
-
+            // add module node to compile unit
+            getAST().addModule(source.getAST());
 
-            if (CompilationUnit.this.progressCallback != null) {
-                CompilationUnit.this.progressCallback.call(source, 
CompilationUnit.this.phase);
+            if (progressCallback != null) {
+                progressCallback.call(source, getPhase());
             }
         }
     };
@@ -789,8 +788,8 @@ public class CompilationUnit extends ProcessingUnit {
             GroovyClassVisitor visitor = verifier;
             try {
                 visitor.visitClass(classNode);
-            } catch (GroovyRuntimeException rpe) {
-                getErrorCollector().addError(new 
SyntaxException(rpe.getMessage(), rpe.getNode()), source);
+            } catch (GroovyRuntimeException gre) {
+                getErrorCollector().addError(new 
SyntaxException(gre.getMessage(), gre.getNode()), source);
             }
 
             visitor = new LabelVerifier(source);
@@ -973,13 +972,13 @@ public class CompilationUnit extends ProcessingUnit {
     private static int getSuperClassCount(ClassNode element) {
         int count = 0;
         while (element != null) {
-            count++;
+            count += 1;
             element = element.getSuperClass();
         }
         return count;
     }
 
-    private int getSuperInterfaceCount(ClassNode element) {
+    private static int getSuperInterfaceCount(ClassNode element) {
         int count = 1;
         ClassNode[] interfaces = element.getInterfaces();
         for (ClassNode anInterface : interfaces) {
diff --git a/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java 
b/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
index ed196db92b..77fc9f53a5 100644
--- a/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/ProcessingUnit.java
@@ -91,8 +91,8 @@ public abstract class ProcessingUnit {
      * Sets the class loader for use by this ProcessingUnit.
      */
     public void setClassLoader(final GroovyClassLoader loader) {
-        // ClassLoaders should only be created inside a doPrivileged block in 
case
-        // this method is invoked by code that does not have security 
permissions.
+        // ClassLoaders should only be created inside doPrivileged block in 
case
+        // this method is invoked by code that does not have security 
permission
         this.classLoader = loader != null ? loader : 
AccessController.doPrivileged(new PrivilegedAction<GroovyClassLoader>() {
             public GroovyClassLoader run() {
                 ClassLoader parent = 
Thread.currentThread().getContextClassLoader();
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java 
b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 915a242c28..2870129056 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -1572,7 +1572,7 @@ public class ResolveVisitor extends 
ClassCodeExpressionTransformer {
             GenericsTypeName gtn = new GenericsTypeName(name);
             ClassNode[] bounds = type.getUpperBounds();
             boolean isWild = QUESTION_MARK.equals(name);
-            boolean toDealWithGenerics = 0 == level || (level > 0 && null != 
genericParameterNames.get(gtn));
+            boolean toDealWithGenerics = 0 == level || (level > 0 && 
genericParameterNames.containsKey(gtn));
 
             if (bounds != null) {
                 boolean nameAdded = false;
diff --git 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index c1b237ed92..1f22a82144 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -179,7 +179,6 @@ public class BinaryExpressionTransformer {
                     }
                 }
             }
-            boolean isAssignment = 
StaticTypeCheckingSupport.isAssignment(operationType);
             MethodCallExpression call;
             MethodNode node = (MethodNode) list[0];
             String name = (String) list[1];
@@ -209,7 +208,7 @@ public class BinaryExpressionTransformer {
                 call.setImplicitThis(false);
             }
             call.setSourcePosition(bin);
-            if (!isAssignment) return call;
+            if (!StaticTypeCheckingSupport.isAssignment(operationType)) return 
call;
             // case of +=, -=, /=, ...
             // the method represents the operation type only, and we must add 
an assignment
             return new BinaryExpression(left, Token.newSymbol("=", 
operation.getStartLine(), operation.getStartColumn()), call);
diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index cb024a3b4c..77440046dc 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -88,6 +88,7 @@ import static 
org.codehaus.groovy.ast.ClassHelper.GSTRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Integer_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Long_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Number_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT;
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.Short_TYPE;
@@ -164,7 +165,6 @@ public abstract class StaticTypeCheckingSupport {
     protected static final ClassNode Collection_TYPE = 
makeWithoutCaching(Collection.class);
     protected static final ClassNode Deprecated_TYPE = 
makeWithoutCaching(Deprecated.class);
 
-    protected static final ExtensionMethodCache EXTENSION_METHOD_CACHE = new 
ExtensionMethodCache();
     protected static final Map<ClassNode, Integer> NUMBER_TYPES = 
Collections.unmodifiableMap(
             new HashMap<ClassNode, Integer>() {
                 private static final long serialVersionUID = 
8841951852732042766L;
@@ -224,6 +224,7 @@ public abstract class StaticTypeCheckingSupport {
      * in an ambiguous method selection for similar methods.
      */
     protected static final Comparator<MethodNode> DGM_METHOD_NODE_COMPARATOR = 
new Comparator<MethodNode>() {
+        @Override
         public int compare(final MethodNode o1, final MethodNode o2) {
             if (o1.getName().equals(o2.getName())) {
                 Parameter[] o1ps = o1.getParameters();
@@ -247,7 +248,9 @@ public abstract class StaticTypeCheckingSupport {
         }
     };
 
-    public static void clearExtensionMethodCache(ClassLoader loader) {
+    protected static final ExtensionMethodCache EXTENSION_METHOD_CACHE = new 
ExtensionMethodCache();
+
+    public static void clearExtensionMethodCache(final ClassLoader loader) {
         EXTENSION_METHOD_CACHE.cache.remove(loader);
     }
 
@@ -257,7 +260,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param expression an expression
      * @return true for array access expressions
      */
-    protected static boolean isArrayAccessExpression(Expression expression) {
+    protected static boolean isArrayAccessExpression(final Expression 
expression) {
         return expression instanceof BinaryExpression && 
isArrayOp(((BinaryExpression) expression).getOperation().getType());
     }
 
@@ -265,18 +268,18 @@ public abstract class StaticTypeCheckingSupport {
      * Called on method call checks in order to determine if a method call 
corresponds to the
      * idiomatic o.with { ... } structure
      *
-     * @param name          name of the method called
-     * @param callArguments arguments of the method
+     * @param name      name of the method called
+     * @param arguments method call arguments
      * @return true if the name is "with" and arguments consist of a single 
closure
      */
-    public static boolean isWithCall(final String name, final Expression 
callArguments) {
-        boolean isWithCall = "with".equals(name) && callArguments instanceof 
ArgumentListExpression;
-        if (isWithCall) {
-            ArgumentListExpression argList = (ArgumentListExpression) 
callArguments;
-            List<Expression> expressions = argList.getExpressions();
-            isWithCall = expressions.size() == 1 && expressions.get(0) 
instanceof ClosureExpression;
+    public static boolean isWithCall(final String name, final Expression 
arguments) {
+        if ("with".equals(name) && arguments instanceof 
ArgumentListExpression) {
+            List<Expression> args = ((ArgumentListExpression) 
arguments).getExpressions();
+            if (args.size() == 1 && args.get(0) instanceof ClosureExpression) {
+                return true;
+            }
         }
-        return isWithCall;
+        return false;
     }
 
     /**
@@ -285,40 +288,40 @@ public abstract class StaticTypeCheckingSupport {
      * @param ve a variable expression
      * @return the target variable
      */
-    protected static Variable findTargetVariable(VariableExpression ve) {
-        final Variable accessedVariable = ve.getAccessedVariable() != null ? 
ve.getAccessedVariable() : ve;
-        if (accessedVariable != ve) {
-            if (accessedVariable instanceof VariableExpression)
+    protected static Variable findTargetVariable(final VariableExpression ve) {
+        Variable accessedVariable = ve.getAccessedVariable();
+        if (accessedVariable != null && accessedVariable != ve) {
+            if (accessedVariable instanceof VariableExpression) {
                 return findTargetVariable((VariableExpression) 
accessedVariable);
+            }
+            return accessedVariable;
         }
-        return accessedVariable;
+        return ve;
     }
 
-
     /**
      * @deprecated Use {@link #findDGMMethodsForClassNode(ClassLoader, 
ClassNode, String)} instead
      */
     @Deprecated
-    protected static Set<MethodNode> findDGMMethodsForClassNode(ClassNode 
clazz, String name) {
+    protected static Set<MethodNode> findDGMMethodsForClassNode(final 
ClassNode clazz, final String name) {
         return 
findDGMMethodsForClassNode(MetaClassRegistryImpl.class.getClassLoader(), clazz, 
name);
     }
 
-    protected static Set<MethodNode> findDGMMethodsForClassNode(final 
ClassLoader loader, ClassNode clazz, String name) {
+    protected static Set<MethodNode> findDGMMethodsForClassNode(final 
ClassLoader loader, final ClassNode clazz, final String name) {
         TreeSet<MethodNode> accumulator = new 
TreeSet<MethodNode>(DGM_METHOD_NODE_COMPARATOR);
         findDGMMethodsForClassNode(loader, clazz, name, accumulator);
         return accumulator;
     }
 
-
     /**
      * @deprecated Use {@link #findDGMMethodsForClassNode(ClassLoader, 
ClassNode, String, TreeSet)} instead
      */
     @Deprecated
-    protected static void findDGMMethodsForClassNode(ClassNode clazz, String 
name, TreeSet<MethodNode> accumulator) {
+    protected static void findDGMMethodsForClassNode(final ClassNode clazz, 
final String name, final TreeSet<MethodNode> accumulator) {
         
findDGMMethodsForClassNode(MetaClassRegistryImpl.class.getClassLoader(), clazz, 
name, accumulator);
     }
 
-    protected static void findDGMMethodsForClassNode(final ClassLoader loader, 
ClassNode clazz, String name, TreeSet<MethodNode> accumulator) {
+    protected static void findDGMMethodsForClassNode(final ClassLoader loader, 
final ClassNode clazz, final String name, final TreeSet<MethodNode> 
accumulator) {
         List<MethodNode> fromDGM = 
EXTENSION_METHOD_CACHE.getExtensionMethods(loader).get(clazz.getName());
         if (fromDGM != null) {
             for (MethodNode node : fromDGM) {
@@ -348,24 +351,25 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks that arguments and parameter types match.
      *
-     * @param params method parameters
-     * @param args   type arguments
      * @return -1 if arguments do not match, 0 if arguments are of the exact 
type and &gt; 0 when one or more argument is
      * not of the exact type but still match
      */
-    public static int allParametersAndArgumentsMatch(Parameter[] params, 
ClassNode[] args) {
-        if (params == null) {
-            params = Parameter.EMPTY_ARRAY;
+    public static int allParametersAndArgumentsMatch(Parameter[] parameters, 
final ClassNode[] argumentTypes) {
+        if (parameters == null) {
+            parameters = Parameter.EMPTY_ARRAY;
         }
         int dist = 0;
-        if (args.length < params.length) return -1;
+        if (argumentTypes.length < parameters.length) {
+            return -1;
+        }
         // we already know there are at least params.length elements in both 
arrays
-        for (int i = 0; i < params.length; i++) {
-            ClassNode paramType = params[i].getType();
-            ClassNode argType = args[i];
-            if (!isAssignableTo(argType, paramType)) return -1;
-            else {
-                if (!paramType.equals(argType)) dist += getDistance(argType, 
paramType);
+        for (int i = 0, n = parameters.length; i < n; i += 1) {
+            ClassNode paramType = parameters[i].getType();
+            ClassNode argType = argumentTypes[i];
+            if (!isAssignableTo(argType, paramType)) {
+                return -1;
+            } else if (!paramType.equals(argType)) {
+                dist += getDistance(argType, paramType);
             }
         }
         return dist;
@@ -375,19 +379,16 @@ public abstract class StaticTypeCheckingSupport {
      * Checks that arguments and parameter types match, expecting that the 
number of parameters is strictly greater
      * than the number of arguments, allowing possible inclusion of default 
parameters.
      *
-     * @param params method parameters
-     * @param args   type arguments
      * @return -1 if arguments do not match, 0 if arguments are of the exact 
type and >0 when one or more argument is
      * not of the exact type but still match
      */
-    static int allParametersAndArgumentsMatchWithDefaultParams(Parameter[] 
params, ClassNode[] args) {
+    static int allParametersAndArgumentsMatchWithDefaultParams(final 
Parameter[] parameters, final ClassNode[] argumentTypes) {
         int dist = 0;
         ClassNode ptype = null;
-        // we already know the lengths are equal
-        for (int i = 0, j = 0; i < params.length; i++) {
-            Parameter param = params[i];
+        for (int i = 0, j = 0, n = parameters.length; i < n; i += 1) {
+            Parameter param = parameters[i];
             ClassNode paramType = param.getType();
-            ClassNode arg = j >= args.length ? null : args[j];
+            ClassNode arg = (j >= argumentTypes.length ? null : 
argumentTypes[j]);
             if (arg == null || !isAssignableTo(arg, paramType)) {
                 if (!param.hasInitialExpression() && (ptype == null || 
!ptype.equals(paramType))) {
                     return -1; // no default value
@@ -395,8 +396,10 @@ public abstract class StaticTypeCheckingSupport {
                 // a default value exists, we can skip this param
                 ptype = null;
             } else {
-                j++;
-                if (!paramType.equals(arg)) dist += getDistance(arg, 
paramType);
+                j += 1;
+                if (!paramType.equals(arg)) {
+                    dist += getDistance(arg, paramType);
+                }
                 if (param.hasInitialExpression()) {
                     ptype = arg;
                 } else {
@@ -410,20 +413,18 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks that excess arguments match the vararg signature parameter.
      *
-     * @param params
-     * @param args
      * @return -1 if no match, 0 if all arguments matches the vararg type and 
>0 if one or more vararg argument is
      * assignable to the vararg type, but still not an exact match
      */
-    static int excessArgumentsMatchesVargsParameter(Parameter[] params, 
ClassNode[] args) {
+    static int excessArgumentsMatchesVargsParameter(final Parameter[] 
parameters, final ClassNode[] argumentTypes) {
         // we already know parameter length is bigger zero and last is a vargs
         // the excess arguments are all put in an array for the vargs call
         // so check against the component type
         int dist = 0;
-        ClassNode vargsBase = params[params.length - 
1].getType().getComponentType();
-        for (int i = params.length; i < args.length; i++) {
-            if (!isAssignableTo(args[i], vargsBase)) return -1;
-            else dist += getClassDistance(vargsBase, args[i]);
+        ClassNode vargsBase = parameters[parameters.length - 
1].getType().getComponentType();
+        for (int i = parameters.length; i < argumentTypes.length; i += 1) {
+            if (!isAssignableTo(argumentTypes[i], vargsBase)) return -1;
+            else dist += getClassDistance(vargsBase, argumentTypes[i]);
         }
         return dist;
     }
@@ -431,8 +432,6 @@ public abstract class StaticTypeCheckingSupport {
     /**
      * Checks if the last argument matches the vararg type.
      *
-     * @param params
-     * @param args
      * @return -1 if no match, 0 if the last argument is exactly the vararg 
type and 1 if of an assignable type
      */
     static int lastArgMatchesVarg(final Parameter[] parameters, final 
ClassNode... argumentTypes) {
@@ -454,15 +453,12 @@ public abstract class StaticTypeCheckingSupport {
      * Checks if a class node is assignable to another. This is used for 
example in
      * assignment checks where you want to verify that the assignment is valid.
      *
-     * @param type
-     * @param toBeAssignedTo
      * @return true if the class node is assignable to the other class node, 
false otherwise
      */
     static boolean isAssignableTo(ClassNode type, ClassNode toBeAssignedTo) {
-        if (UNKNOWN_PARAMETER_TYPE == type) return true;
-        if (type == toBeAssignedTo) return true;
-        if (isPrimitiveType(toBeAssignedTo)) toBeAssignedTo = 
getWrapper(toBeAssignedTo);
+        if (type == toBeAssignedTo || type == UNKNOWN_PARAMETER_TYPE) return 
true;
         if (isPrimitiveType(type)) type = getWrapper(type);
+        if (isPrimitiveType(toBeAssignedTo)) toBeAssignedTo = 
getWrapper(toBeAssignedTo);
         if (NUMBER_TYPES.containsKey(type.redirect()) && 
NUMBER_TYPES.containsKey(toBeAssignedTo.redirect())) {
             return NUMBER_TYPES.get(type.redirect()) <= 
NUMBER_TYPES.get(toBeAssignedTo.redirect());
         }
@@ -478,9 +474,7 @@ public abstract class StaticTypeCheckingSupport {
         }
         if (implementsInterfaceOrIsSubclassOf(type, toBeAssignedTo)) {
             if (toBeAssignedTo.equals(OBJECT_TYPE)) return true;
-            if (toBeAssignedTo.isUsingGenerics()) {
-                // perform additional check on generics
-                // ? extends toBeAssignedTo
+            if (toBeAssignedTo.isUsingGenerics()) { // perform additional 
checks on generics
                 GenericsType gt = 
GenericsUtils.buildWildcardType(toBeAssignedTo);
                 return gt.isCompatibleWith(type);
             }
@@ -492,33 +486,30 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
-    static boolean isVargs(Parameter[] params) {
-        if (params.length == 0) return false;
-        if (params[params.length - 1].getType().isArray()) return true;
-        return false;
+    static boolean isVargs(final Parameter[] parameters) {
+        if (parameters == null || parameters.length == 0) return false;
+        return (parameters[parameters.length - 1].getType().isArray());
     }
 
-    public static boolean isCompareToBoolean(int op) {
-        return op == COMPARE_GREATER_THAN ||
-                op == COMPARE_GREATER_THAN_EQUAL ||
-                op == COMPARE_LESS_THAN ||
-                op == COMPARE_LESS_THAN_EQUAL;
+    public static boolean isCompareToBoolean(final int op) {
+        return op == COMPARE_LESS_THAN || op == COMPARE_LESS_THAN_EQUAL
+                || op == COMPARE_GREATER_THAN || op == 
COMPARE_GREATER_THAN_EQUAL;
     }
 
-    static boolean isArrayOp(int op) {
+    static boolean isArrayOp(final int op) {
         return op == LEFT_SQUARE_BRACKET;
     }
 
-    static boolean isBoolIntrinsicOp(int op) {
+    static boolean isBoolIntrinsicOp(final int op) {
         return op == LOGICAL_AND || op == LOGICAL_OR || op == 
COMPARE_NOT_IDENTICAL || op == COMPARE_IDENTICAL ||
                 op == MATCH_REGEX || op == KEYWORD_INSTANCEOF;
     }
 
-    static boolean isPowerOperator(int op) {
+    static boolean isPowerOperator(final int op) {
         return op == POWER || op == POWER_EQUAL;
     }
 
-    static String getOperationName(int op) {
+    static String getOperationName(final int op) {
         switch (op) {
             case COMPARE_EQUAL:
             case COMPARE_NOT_EQUAL:
@@ -594,7 +585,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    static boolean isShiftOperation(String name) {
+    static boolean isShiftOperation(final String name) {
         return "leftShift".equals(name) || "rightShift".equals(name) || 
"rightShiftUnsigned".equals(name);
     }
 
@@ -603,7 +594,7 @@ public abstract class StaticTypeCheckingSupport {
      * operation "left op right" will have a result in the same type class In 
Groovy on numbers that is +,-,* as well as
      * their variants with equals.
      */
-    static boolean isOperationInGroup(int op) {
+    static boolean isOperationInGroup(final int op) {
         switch (op) {
             case PLUS:
             case PLUS_EQUAL:
@@ -617,7 +608,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    static boolean isBitOperator(int op) {
+    static boolean isBitOperator(final int op) {
         switch (op) {
             case BITWISE_OR_EQUAL:
             case BITWISE_OR:
@@ -631,7 +622,7 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-    public static boolean isAssignment(int op) {
+    public static boolean isAssignment(final int op) {
         switch (op) {
             case ASSIGN:
             case LOGICAL_OR_EQUAL:
@@ -727,10 +718,9 @@ public abstract class StaticTypeCheckingSupport {
             return true;
         }
 
-        // if right is array, map or collection we try invoking the
-        // constructor
+        // if right is array, map or collection we try invoking the constructor
         if (allowConstructorCoercion && 
isGroovyConstructorCompatible(rightExpression)) {
-            //TODO: in case of the array we could maybe make a partial check
+            // TODO: in case of the array we could maybe make a partial check
             if (leftRedirect.isArray() && rightRedirect.isArray()) {
                 return 
checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), 
rightRedirect.getComponentType());
             } else if (rightRedirect.isArray() && !leftRedirect.isArray()) {
@@ -787,18 +777,15 @@ public abstract class StaticTypeCheckingSupport {
      * @return true if it's an Object, String, boolean, Boolean or Class.
      */
     public static boolean isWildcardLeftHandSide(final ClassNode node) {
-        if (OBJECT_TYPE.equals(node) ||
-                STRING_TYPE.equals(node) ||
-                boolean_TYPE.equals(node) ||
-                Boolean_TYPE.equals(node) ||
-                CLASS_Type.equals(node)) {
-            return true;
-        }
-        return false;
+        return (OBJECT_TYPE.equals(node)
+                || STRING_TYPE.equals(node)
+                || boolean_TYPE.equals(node)
+                || Boolean_TYPE.equals(node)
+                || CLASS_Type.equals(node));
     }
 
-    public static boolean isBeingCompiled(ClassNode node) {
-        return node.getCompileUnit() != null;
+    public static boolean isBeingCompiled(final ClassNode node) {
+        return (node.getCompileUnit() != null);
     }
 
     @Deprecated
@@ -995,8 +982,7 @@ public abstract class StaticTypeCheckingSupport {
         if (c.equals(interfaceClass)) return 0;
         ClassNode[] interfaces = c.getInterfaces();
         int max = -1;
-        for (int i = 0; i < interfaces.length; i++) {
-            final ClassNode anInterface = interfaces[i];
+        for (ClassNode anInterface : interfaces) {
             int sub = getMaximumInterfaceDistance(anInterface, interfaceClass);
             // we need to keep the -1 to track the mismatch, a +1
             // by any means could let it look like a direct match
@@ -1046,25 +1032,8 @@ public abstract class StaticTypeCheckingSupport {
      * @param node the node to test
      * @return true if it is using any placeholder in generics types
      */
-    public static boolean isUsingUncheckedGenerics(ClassNode node) {
-        if (node.isArray()) return 
isUsingUncheckedGenerics(node.getComponentType());
-        if (node.isUsingGenerics()) {
-            GenericsType[] genericsTypes = node.getGenericsTypes();
-            if (genericsTypes != null) {
-                for (GenericsType genericsType : genericsTypes) {
-                    if (genericsType.isPlaceholder()) {
-                        return true;
-                    } else {
-                        if (isUsingUncheckedGenerics(genericsType.getType())) {
-                            return true;
-                        }
-                    }
-                }
-            }
-        } else {
-            return false;
-        }
-        return false;
+    public static boolean isUsingUncheckedGenerics(final ClassNode node) {
+        return GenericsUtils.hasUnresolvedGenerics(node);
     }
 
     /**
@@ -1216,7 +1185,6 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static Parameter[] makeRawTypes(Parameter[] params, 
Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
-
         Parameter[] newParam = new Parameter[params.length];
         for (int i = 0; i < params.length; i++) {
             Parameter oldP = params[i];
@@ -1311,7 +1279,7 @@ public abstract class StaticTypeCheckingSupport {
         Map<GenericsTypeName, GenericsType> contextPlaceholders = 
extractGenericsParameterMapOfThis(m);
         Parameter[] methodParameters = m.getParameters();
         Parameter[] params = new Parameter[methodParameters.length];
-        for (int i = 0; i < methodParameters.length; i++) {
+        for (int i = 0, n = methodParameters.length; i < n; i += 1) {
             Parameter methodParameter = methodParameters[i];
             ClassNode paramType = methodParameter.getType();
             params[i] = buildParameter(genericFromReceiver, 
contextPlaceholders, methodParameter, paramType);
@@ -1323,7 +1291,7 @@ public abstract class StaticTypeCheckingSupport {
      * Given a parameter, builds a new parameter for which the known generics 
placeholders are resolved.
      *
      * @param genericFromReceiver      resolved generics from the receiver of 
the message
-     * @param placeholdersFromContext, resolved generics from the method 
context
+     * @param placeholdersFromContext  resolved generics from the method 
context
      * @param methodParameter          the method parameter for which we want 
to resolve generic types
      * @param paramType                the (unresolved) type of the method 
parameter
      * @return a new parameter with the same name and type as the original 
one, but with resolved generic types
@@ -1350,7 +1318,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param cn a class node for which to check if it is using generics
      * @return true if the type (or component type) is using generics
      */
-    public static boolean isUsingGenericsOrIsArrayUsingGenerics(ClassNode cn) {
+    public static boolean isUsingGenericsOrIsArrayUsingGenerics(final 
ClassNode cn) {
         if (cn.isArray()) {
             return 
isUsingGenericsOrIsArrayUsingGenerics(cn.getComponentType());
         }
@@ -1388,36 +1356,39 @@ public abstract class StaticTypeCheckingSupport {
         if (type.isArray()) {
             return fullyResolveType(type.getComponentType(), 
placeholders).makeArray();
         }
-        if (type.isUsingGenerics()) {
-            if (type.isGenericsPlaceHolder()) {
-                GenericsType gt = placeholders.get(new 
GenericsTypeName(type.getUnresolvedName()));
-                if (gt != null) {
-                    return gt.getType();
-                }
-                ClassNode cn = extractType(type.asGenericsType()); // 
GROOVY-10756
-                return cn != type ? cn : OBJECT_TYPE; // do not return 
placeholder
-            } else {
-                GenericsType[] gts = type.getGenericsTypes();
-                if (gts != null) {  final int n = gts.length;
-                    GenericsType[] copy = new GenericsType[n];
-                    for (int i = 0; i < n; i += 1) {
-                        GenericsType gt = gts[i];
-                        if (gt.isPlaceholder()) {
-                            GenericsTypeName gtn = new 
GenericsTypeName(gt.getName());
-                            copy[i] = placeholders.containsKey(gtn)
-                                ? placeholders.get(gtn) : 
extractType(gt).asGenericsType();
-                        } else {
-                            copy[i] = fullyResolve(gt, placeholders);
-                        }
-                    }
-                    gts = copy;
+        if (!type.isUsingGenerics()) {
+            return type;
+        }
+        if (type.isGenericsPlaceHolder()) {
+            GenericsType gt = placeholders.get(new 
GenericsTypeName(type.getUnresolvedName()));
+            if (gt != null) {
+                return gt.getType();
+            }
+            ClassNode cn = extractType(type.asGenericsType()); // GROOVY-10756
+            return cn != type ? cn : OBJECT_TYPE; // do not return placeholder
+        }
+
+        GenericsType[] gts = type.getGenericsTypes();
+        if (gts != null && gts.length > 0) {
+            gts = gts.clone();
+            for (int i = 0, n = gts.length; i < n; i += 1) {
+                GenericsType gt = gts[i];
+                if (gt.isPlaceholder()) { String name = gt.getName();
+                    gt = placeholders.get(new GenericsTypeName(name));
+                    if (gt == null) gt = extractType(gts[i]).asGenericsType();
+                    // GROOVY-10364: skip placeholder from the enclosing 
context
+                    if (gt.isPlaceholder() && gt.getName().equals(name)) 
continue;
+
+                    gts[i] = gt;
+                } else {
+                    gts[i] = fullyResolve(gt, placeholders);
                 }
-                ClassNode cn = type.getPlainNodeReference();
-                cn.setGenericsTypes(gts);
-                return cn;
             }
         }
-        return type;
+
+        ClassNode cn = type.getPlainNodeReference();
+        cn.setGenericsTypes(gts);
+        return cn;
     }
 
     /**
@@ -1431,12 +1402,9 @@ public abstract class StaticTypeCheckingSupport {
             // called with null
             return !isPrimitiveType(parameterType);
         }
-        if (!isAssignableTo(argumentType, parameterType) && !lastArg) {
-            // incompatible assignment
-            return false;
-        }
-        if (!isAssignableTo(argumentType, parameterType) && lastArg) {
-            if (parameterType.isArray()) {
+        boolean isArrayParameter = parameterType.isArray();
+        if (!isAssignableTo(argumentType, parameterType)) {
+            if (isArrayParameter && lastArg) {
                 if (!isAssignableTo(argumentType, 
parameterType.getComponentType())) {
                     return false;
                 }
@@ -1444,20 +1412,21 @@ public abstract class StaticTypeCheckingSupport {
                 return false;
             }
         }
-        if (parameterType.isUsingGenerics() && argumentType.isUsingGenerics()) 
{
-            GenericsType gt = GenericsUtils.buildWildcardType(parameterType);
-            if (!gt.isCompatibleWith(argumentType)) {
-                boolean samCoercion = isSAMType(parameterType) && 
argumentType.equals(CLOSURE_TYPE);
-                if (!samCoercion) return false;
-            }
-        } else if (parameterType.isArray() && argumentType.isArray()) {
+        if (isArrayParameter && argumentType.isArray()) {
             // verify component type
             return 
typeCheckMethodArgumentWithGenerics(parameterType.getComponentType(), 
argumentType.getComponentType(), lastArg);
-        } else if (lastArg && parameterType.isArray()) {
+
+        } else if (isArrayParameter && lastArg) {
             // verify component type, but if we reach that point, the only 
possibility is that the argument is
             // the last one of the call, so we're in the cast of a vargs call
             // (otherwise, we face a type checker bug)
             return 
typeCheckMethodArgumentWithGenerics(parameterType.getComponentType(), 
argumentType, lastArg);
+
+        } else if (parameterType.isUsingGenerics() && 
argumentType.isUsingGenerics()) {
+            if 
(!GenericsUtils.buildWildcardType(parameterType).isCompatibleWith(argumentType))
 {
+                boolean samCoercion = argumentType.equals(CLOSURE_TYPE) && 
isSAMType(parameterType);
+                if (!samCoercion) return false;
+            }
         }
         return true;
     }
@@ -1547,9 +1516,8 @@ public abstract class StaticTypeCheckingSupport {
         if (lastArg &&
                 type.isArray() && 
type.getComponentType().isGenericsPlaceHolder() &&
                 !wrappedArgument.isArray() && 
wrappedArgument.isGenericsPlaceHolder()) {
-            // GROOVY-8090 handle generics varargs, e.g. `U x = ...; 
Arrays.asList(x)`
+            // GROOVY-8090: handle generics varargs, e.g. `U x = ...; 
Arrays.asList(x)`
             // we should connect the type of vararg(e.g. T is the type of 
T...) to the argument type
-
             type = type.getComponentType();
         }
         // the context we compare with in the end is the one of the callsite
@@ -1615,29 +1583,28 @@ public abstract class StaticTypeCheckingSupport {
         return true;
     }
 
-    private static boolean compatibleConnection(GenericsType resolved, 
GenericsType connection) {
-        GenericsType gt = connection;
-        if (!connection.isWildcard()) gt = buildWildcardType(connection);
-        if (resolved.isPlaceholder() && resolved.getUpperBounds() != null &&
-                resolved.getUpperBounds().length == 1 && 
!resolved.getUpperBounds()[0].isGenericsPlaceHolder() &&
-                
resolved.getUpperBounds()[0].getName().equals("java.lang.Object")) {
+    private static boolean compatibleConnection(final GenericsType resolved, 
final GenericsType connection) {
+        if (resolved.isPlaceholder()
+                && resolved.getUpperBounds() != null
+                && resolved.getUpperBounds().length == 1
+                && !resolved.getUpperBounds()[0].isGenericsPlaceHolder()
+                && resolved.getUpperBounds()[0].getName().equals(OBJECT)) {
             return true;
         }
         ClassNode compareNode;
         if (hasNonTrivialBounds(resolved)) {
             compareNode = getCombinedBoundType(resolved);
             compareNode = compareNode.redirect().getPlainNodeReference();
+        } else if (!resolved.isPlaceholder()) {
+            compareNode = resolved.getType().getPlainNodeReference();
         } else {
-            if (!resolved.isPlaceholder()) {
-                compareNode = resolved.getType().getPlainNodeReference();
-            } else {
-                return true;
-            }
+            return true;
         }
+        GenericsType gt = connection.isWildcard() ? connection : 
buildWildcardType(connection);
         return gt.isCompatibleWith(compareNode);
     }
 
-    private static void addMissingEntries(Map<GenericsTypeName, GenericsType> 
connections, Map<GenericsTypeName, GenericsType> resolved) {
+    private static void addMissingEntries(final Map<GenericsTypeName, 
GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolved) {
         for (Map.Entry<GenericsTypeName, GenericsType> entry : 
connections.entrySet()) {
             if (resolved.containsKey(entry.getKey())) continue;
             GenericsType gt = entry.getValue();
@@ -1691,24 +1658,26 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static ClassNode extractType(GenericsType gt) {
+        ClassNode cn;
         if (!gt.isPlaceholder()) {
-            return gt.getType();
-        }
-        // For a placeholder, a type based on the generics type is used for 
the compatibility check, to match on
-        // the actual bounds and not the name of the placeholder.
-        ClassNode replacementType = gt.getType().redirect();
-        if (gt.getType().getGenericsTypes() != null) {
-            GenericsType realGt = gt.getType().getGenericsTypes()[0];
-            if (realGt.getLowerBound() != null) {
-                replacementType = realGt.getLowerBound();
-            } else if (realGt.getUpperBounds() != null && 
realGt.getUpperBounds().length > 0) {
-                replacementType = realGt.getUpperBounds()[0];
+            cn = gt.getType();
+        } else {
+            // discard the placeholder
+            cn = gt.getType().redirect();
+
+            if (gt.getType().getGenericsTypes() != null)
+                gt = gt.getType().getGenericsTypes()[0];
+
+            if (gt.getLowerBound() != null) {
+                cn = gt.getLowerBound();
+            } else if (gt.getUpperBounds() != null) {
+                cn = gt.getUpperBounds()[0];
             }
         }
-        return replacementType;
+        return cn;
     }
 
-    private static boolean equalIncludingGenerics(GenericsType orig, 
GenericsType copy) {
+    private static boolean equalIncludingGenerics(final GenericsType orig, 
final GenericsType copy) {
         if (orig == copy) return true;
         if (orig.isPlaceholder() != copy.isPlaceholder()) return false;
         if (orig.isWildcard() != copy.isWildcard()) return false;
@@ -1724,14 +1693,14 @@ public abstract class StaticTypeCheckingSupport {
         if ((upper1 == null) ^ (upper2 == null)) return false;
         if (upper1 != upper2) {
             if (upper1.length != upper2.length) return false;
-            for (int i = 0; i < upper1.length; i++) {
+            for (int i = 0, n = upper1.length; i < n; i += 1) {
                 if (!equalIncludingGenerics(upper1[i], upper2[i])) return 
false;
             }
         }
         return true;
     }
 
-    private static boolean equalIncludingGenerics(ClassNode orig, ClassNode 
copy) {
+    private static boolean equalIncludingGenerics(final ClassNode orig, final 
ClassNode copy) {
         if (orig == copy) return true;
         if (orig.isGenericsPlaceHolder() != copy.isGenericsPlaceHolder()) 
return false;
         if (!orig.equals(copy)) return false;
@@ -1740,7 +1709,7 @@ public abstract class StaticTypeCheckingSupport {
         if ((gt1 == null) ^ (gt2 == null)) return false;
         if (gt1 != gt2) {
             if (gt1.length != gt2.length) return false;
-            for (int i = 0; i < gt1.length; i++) {
+            for (int i = 0, n = gt1.length; i < n; i += 1) {
                 if (!equalIncludingGenerics(gt1[i], gt2[i])) return false;
             }
         }
@@ -1813,7 +1782,7 @@ public abstract class StaticTypeCheckingSupport {
         return corrected;
     }
 
-    private static void extractGenericsConnections(Map<GenericsTypeName, 
GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
+    private static void extractGenericsConnections(final Map<GenericsTypeName, 
GenericsType> connections, final GenericsType[] usage, final GenericsType[] 
declaration) {
         // if declaration does not provide generics, there is no connection to 
make
         if (usage == null || declaration == null || declaration.length == 0) 
return;
         final int n; if ((n = usage.length) != declaration.length) return;
@@ -1874,7 +1843,7 @@ public abstract class StaticTypeCheckingSupport {
         return newGTs;
     }
 
-    private static GenericsType applyGenericsContext(final 
Map<GenericsTypeName, GenericsType> spec, final GenericsType gt) {
+    private static GenericsType applyGenericsContext(Map<GenericsTypeName, 
GenericsType> spec, GenericsType gt) {
         if (gt.isPlaceholder()) {
             GenericsTypeName name = new GenericsTypeName(gt.getName());
             GenericsType specType = spec.get(name);
@@ -1962,8 +1931,8 @@ public abstract class StaticTypeCheckingSupport {
         return cn;
     }
 
-    static ClassNode getCombinedBoundType(GenericsType genericsType) {
-        //TODO: this method should really return some kind of meta ClassNode
+    static ClassNode getCombinedBoundType(final GenericsType genericsType) {
+        // TODO: this method should really return some kind of meta ClassNode
         // representing the combination of all bounds. The code here, just 
picks
         // something out to be able to proceed and is not actually correct
         if (hasNonTrivialBounds(genericsType)) {
@@ -1973,7 +1942,7 @@ public abstract class StaticTypeCheckingSupport {
         return genericsType.getType();
     }
 
-    private static Map<GenericsTypeName, GenericsType> 
getGenericsParameterMapOfThis(ClassNode cn) {
+    private static Map<GenericsTypeName, GenericsType> 
getGenericsParameterMapOfThis(final ClassNode cn) {
         if (cn == null) return null;
         Map<GenericsTypeName, GenericsType> map = null;
         if (cn.getEnclosingMethod() != null) {
@@ -1991,7 +1960,7 @@ public abstract class StaticTypeCheckingSupport {
      * @param type A parameterized type
      * @return A parameterized type with more precise wildcards
      */
-    static ClassNode boundUnboundedWildcards(ClassNode type) {
+    static ClassNode boundUnboundedWildcards(final ClassNode type) {
         if (type.isArray()) {
             return 
boundUnboundedWildcards(type.getComponentType()).makeArray();
         }
@@ -2003,19 +1972,18 @@ public abstract class StaticTypeCheckingSupport {
         return newType;
     }
 
-    private static GenericsType[] boundUnboundedWildcards(GenericsType[] 
usage, GenericsType[] declaration) {
+    private static GenericsType[] boundUnboundedWildcards(final GenericsType[] 
usage, final GenericsType[] declaration) {
         GenericsType[] newGts = new GenericsType[usage.length];
-        for (int i = 0; i < usage.length; i++) {
+        for (int i = 0, n = usage.length; i < n; i += 1) {
             newGts[i] = boundUnboundedWildcard(usage[i], declaration[i]);
         }
         return newGts;
     }
 
-    private static GenericsType boundUnboundedWildcard(GenericsType gt, 
GenericsType spec) {
+    private static GenericsType boundUnboundedWildcard(final GenericsType gt, 
final GenericsType spec) {
         if (isUnboundedWildcard(gt)) {
             ClassNode base = makeWithoutCaching("?");
-            // The bounds on the declared type are at least as good as the 
ones on an unbounded wildcard, since it has
-            // none!
+            // The bounds on the declared type are at least as good as the 
ones on an unbounded wildcard, since it has none!
             GenericsType newGt = new GenericsType(base, spec.getUpperBounds(), 
spec.getLowerBound());
             newGt.setWildcard(true);
             return newGt;
@@ -2032,7 +2000,7 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
-    static Map<GenericsTypeName, GenericsType> 
extractGenericsParameterMapOfThis(TypeCheckingContext context) {
+    static Map<GenericsTypeName, GenericsType> 
extractGenericsParameterMapOfThis(final TypeCheckingContext context) {
         ClassNode cn = context.getEnclosingClassNode();
         MethodNode mn = context.getEnclosingMethod();
         // GROOVY-9570: find the innermost class or method
@@ -2042,7 +2010,7 @@ public abstract class StaticTypeCheckingSupport {
         return extractGenericsParameterMapOfThis(mn);
     }
 
-    static Map<GenericsTypeName, GenericsType> 
extractGenericsParameterMapOfThis(MethodNode mn) {
+    static Map<GenericsTypeName, GenericsType> 
extractGenericsParameterMapOfThis(final MethodNode mn) {
         if (mn == null) return null;
 
         Map<GenericsTypeName, GenericsType> map;
@@ -2055,7 +2023,7 @@ public abstract class StaticTypeCheckingSupport {
         return mergeGenerics(map, mn.getGenericsTypes());
     }
 
-    private static Map<GenericsTypeName, GenericsType> 
mergeGenerics(Map<GenericsTypeName, GenericsType> current, GenericsType[] 
newGenerics) {
+    private static Map<GenericsTypeName, GenericsType> 
mergeGenerics(Map<GenericsTypeName, GenericsType> current, final GenericsType[] 
newGenerics) {
         if (newGenerics == null || newGenerics.length == 0) return current;
         if (current == null) current = new HashMap<GenericsTypeName, 
GenericsType>();
         for (GenericsType gt : newGenerics) {
@@ -2228,6 +2196,9 @@ public abstract class StaticTypeCheckingSupport {
         return node.getSuperClass() != null && 
isParameterizedWithString(node.getUnresolvedSuperClass());
     }
 
+    /**
+     * Determines if node is a raw type or references any generics 
placeholders.
+     */
     public static boolean missesGenericsTypes(ClassNode cn) {
         while (cn.isArray()) cn = cn.getComponentType();
         GenericsType[] cnGenerics = cn.getGenericsTypes();
@@ -2236,15 +2207,16 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     /**
-     * A helper method that can be used to evaluate expressions as found in 
annotation
-     * parameters. For example, it will evaluate a constant, be it referenced 
directly as
-     * an integer or as a reference to a field.
+     * Evaluates expressions as found in annotation parameters.  For example, 
it
+     * will evaluate a constant, be it referenced directly as an integer or as 
a
+     * reference to a field.
      * <p>
-     * If this method throws an exception, then the expression cannot be 
evaluated on its own.
+     * If the expression cannot be evaluated on its own, an exception is 
thrown.
      *
      * @param expr   the expression to be evaluated
      * @param config the compiler configuration
      * @return the result of the expression
+     * @throws GroovyBugError
      */
     public static Object evaluateExpression(final Expression expr, final 
CompilerConfiguration config) {
         String className = 
"Expression$"+UUID.randomUUID().toString().replace('-', '$');
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 50e83b5b21..9e4774bbaa 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3337,7 +3337,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                 Expression type = annotation.getMember("type");
                 Integer stInt = Closure.OWNER_FIRST;
                 if (strategy != null) {
-                    stInt = (Integer) evaluateExpression(castX(Integer_TYPE, 
strategy), typeCheckingContext.source.getConfiguration());
+                    stInt = (Integer) evaluateExpression(castX(Integer_TYPE, 
strategy), getSourceUnit().getConfiguration());
                 }
                 if (value instanceof ClassExpression && 
!value.getType().equals(DELEGATES_TO_TARGET)) {
                     if (genericTypeIndex != null) {
diff --git 
a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java 
b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index e218e17f02..19fc799e4f 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -225,8 +225,8 @@ public class TraitASTTransformation extends 
AbstractASTTransformation implements
         for (final MethodNode methodNode : methods) {
             boolean declared = methodNode.getDeclaringClass() == cNode;
             if (declared) {
-                if (!methodNode.isSynthetic() && (methodNode.isProtected() || 
methodNode.getModifiers()==0)) {
-                    unit.addError(new SyntaxException("Cannot have 
protected/package private method in a trait (" + cNode.getName() + "#" + 
methodNode.getTypeDescriptor() + ")",
+                if (!methodNode.isSynthetic() && (methodNode.isProtected() || 
(!methodNode.isPrivate() && !methodNode.isPublic()))) {
+                    unit.addError(new SyntaxException("Cannot have 
protected/package-private method in a trait (" + cNode.getName() + "#" + 
methodNode.getTypeDescriptor() + ")",
                             methodNode.getLineNumber(), 
methodNode.getColumnNumber()));
                     return null;
                 }
@@ -269,7 +269,6 @@ public class TraitASTTransformation extends 
AbstractASTTransformation implements
         // clear properties to avoid generation of methods
         cNode.getProperties().clear();
 
-        // copy annotations
         copyClassAnnotations(cNode, helper);
         markAsGenerated(cNode, helper);
 
@@ -570,7 +569,7 @@ public class TraitASTTransformation extends 
AbstractASTTransformation implements
         dummyField = new FieldNode(
                 dummyFieldName,
                 ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
-                field.getOriginType(),
+                field.getOriginType().getPlainNodeReference(),
                 fieldHelper,
                 null
         );
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy 
b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 3c8ce122d7..31256795f4 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -428,6 +428,23 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    @NotYetImplemented
+    void testReturnTypeInferenceWithMethodGenerics1y() {
+        assertScript '''
+            interface Type { }
+            class Pogo implements Type { String name }
+            class CacheManager {
+                def <T extends Type> T fromCache(String key) {
+                    new Pogo()
+                }
+            }
+
+            def cacheManager = new CacheManager( )
+            Pogo pogo = cacheManager.fromCache('')
+            pogo.name
+        '''
+    }
+
     // GROOVY-10067
     @NotYetImplemented
     void testReturnTypeInferenceWithMethodGenerics11() {
@@ -1461,7 +1478,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
     }
 
     // GROOVY-10343
-    @NotYetImplemented
     void testDiamondInferenceFromConstructor27() {
         assertScript '''
             class C<T1, T2 extends T1> {

Reply via email to