You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/11/13 18:09:10 UTC

[groovy] 01/02: make fewer `LowestUpperBoundClassNode` instances

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

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

commit 2feab7d0358ceda2654e20d518ab5d58b0732e57
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 13 11:52:41 2021 -0600

    make fewer `LowestUpperBoundClassNode` instances
---
 .../groovy/ast/tools/WideningCategories.java       | 272 ++++++++-------------
 .../stc/ArraysAndCollectionsSTCTest.groovy         |  16 +-
 2 files changed, 114 insertions(+), 174 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java b/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
index e7de73f..c413668 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/WideningCategories.java
@@ -26,13 +26,12 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
 
 import static java.util.stream.IntStream.range;
 import static org.codehaus.groovy.ast.ClassHelper.Number_TYPE;
@@ -41,6 +40,7 @@ import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.byte_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.getNextSuperClass;
 import static org.codehaus.groovy.ast.ClassHelper.getUnwrapper;
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.ast.ClassHelper.int_TYPE;
@@ -90,23 +90,6 @@ public class WideningCategories {
     );
 
     /**
-     * A comparator which is used in case we generate a virtual lower upper bound class node. In that case,
-     * since a concrete implementation should be used at compile time, we must ensure that interfaces are
-     * always sorted. It is not important what sort is used, as long as the result is constant.
-     */
-    private static final Comparator<ClassNode> INTERFACE_CLASSNODE_COMPARATOR = (cn1, cn2) -> {
-        int interfaceCount1 = cn1.getInterfaces().length;
-        int interfaceCount2 = cn2.getInterfaces().length;
-        if (interfaceCount1 > interfaceCount2) return -1;
-        if (interfaceCount1 < interfaceCount2) return 1;
-        int methodCount1 = cn1.getMethods().size();
-        int methodCount2 = cn2.getMethods().size();
-        if (methodCount1 > methodCount2) return -1;
-        if (methodCount1 < methodCount2) return 1;
-        return cn1.getName().compareTo(cn2.getName());
-    };
-
-    /**
      * Used to check if a type is an int or Integer.
      * @param type the type to check
      */
@@ -226,20 +209,19 @@ public class WideningCategories {
             // We must create a classnode for which the "superclass" is potentially parameterized
             // plus the interfaces
             ClassNode superClass = lub.getSuperClass();
-            ClassNode psc = superClass.isUsingGenerics()?parameterizeLowestUpperBound(superClass, a, b, lub):superClass;
+            if (superClass.redirect().getGenericsTypes() != null) {
+                superClass = parameterizeLowestUpperBound(superClass, a, b, lub);
+            }
 
-            ClassNode[] interfaces = lub.getInterfaces();
-            ClassNode[] pinterfaces = interfaces.clone();
+            ClassNode[] interfaces = lub.getInterfaces().clone();
             for (int i = 0, n = interfaces.length; i < n; i += 1) {
-                final ClassNode icn = interfaces[i];
-                if (icn.isUsingGenerics()) {
-                    pinterfaces[i] = parameterizeLowestUpperBound(icn, a, b, lub);
-                } else {
-                    pinterfaces[i] = icn;
+                ClassNode icn = interfaces[i];
+                if (icn.redirect().getGenericsTypes() != null) {
+                    interfaces[i] = parameterizeLowestUpperBound(icn, a, b, lub);
                 }
             }
 
-            return new LowestUpperBoundClassNode(((LowestUpperBoundClassNode)lub).name, psc, pinterfaces);
+            return new LowestUpperBoundClassNode(((LowestUpperBoundClassNode)lub).name, superClass, interfaces);
         } else {
             return parameterizeLowestUpperBound(lub, a, b, lub);
         }
@@ -259,7 +241,7 @@ public class WideningCategories {
      * @return the class node representing the parameterized lowest upper bound
      */
     private static ClassNode parameterizeLowestUpperBound(final ClassNode lub, final ClassNode a, final ClassNode b, final ClassNode fallback) {
-        if (!lub.isUsingGenerics() || a.toString(false).equals(b.toString(false))) return lub;
+        if (a.toString(false).equals(b.toString(false))) return lub;
         // a common super type exists, all we have to do is to parameterize
         // it according to the types provided by the two class nodes
         ClassNode holderForA = findGenericsTypeHolderForClass(a, lub);
@@ -272,68 +254,54 @@ public class WideningCategories {
         }
         int n = agt.length; GenericsType[] lubGTs = new GenericsType[n];
         for (int i = 0; i < n; i += 1) {
-            if (agt[i].toString().equals(bgt[i].toString())) {
-                lubGTs[i] = agt[i];
-                continue;
-            }
-            ClassNode t1 = agt[i].getType();
-            ClassNode t2 = bgt[i].getType();
+            ClassNode t1 = upperBound(agt[i]);
+            ClassNode t2 = upperBound(bgt[i]);
             ClassNode basicType;
             if (areEqualWithGenerics(t1, isPrimitiveType(a)?getWrapper(a):a) && areEqualWithGenerics(t2, isPrimitiveType(b)?getWrapper(b):b)) {
-                // we are facing a self-referencing type !
-                basicType = fallback;
+                // "String implements Comparable<String>" and "StringBuffer implements Comparable<StringBuffer>"
+                basicType = fallback; // do not loop
             } else {
                 basicType = lowestUpperBound(t1, t2);
             }
-            if (t1.equals(t2)) {
-                lubGTs[i] = basicType.asGenericsType();
-            } else {
+            if (agt[i].isWildcard() || bgt[i].isWildcard() || !t1.equals(t2)) {
                 lubGTs[i] = GenericsUtils.buildWildcardType(basicType);
+            } else {
+                lubGTs[i] = basicType.asGenericsType();
             }
         }
-        ClassNode plain = lub.getPlainNodeReference();
-        plain.setGenericsTypes(lubGTs);
-        return plain;
+        return GenericsUtils.makeClassSafe0(lub, lubGTs);
     }
 
-    private static ClassNode findGenericsTypeHolderForClass(ClassNode source, final ClassNode type) {
+    private static ClassNode findGenericsTypeHolderForClass(ClassNode source, final ClassNode target) {
         if (isPrimitiveType(source)) source = getWrapper(source);
-        if (source.equals(type)) return source;
-        if (type.isInterface()) {
-            for (ClassNode interfaceNode : source.getAllInterfaces()) {
-                if (interfaceNode.equals(type)) {
-                    ClassNode parameterizedInterface = GenericsUtils.parameterizeType(source, interfaceNode);
-                    return parameterizedInterface;
-                }
-            }
-        }
-        ClassNode superClass = source.getUnresolvedSuperClass();
-        // copy generic type information if available
-        if (superClass!=null && superClass.isUsingGenerics()) {
-            Map<GenericsType.GenericsTypeName, GenericsType> genericsTypeMap = GenericsUtils.extractPlaceholders(source);
-            GenericsType[] genericsTypes = superClass.getGenericsTypes();
-            if (genericsTypes!=null) {
-                GenericsType[] copyTypes = new GenericsType[genericsTypes.length];
-                for (int i = 0; i < genericsTypes.length; i++) {
-                    GenericsType genericsType = genericsTypes[i];
-                    GenericsType.GenericsTypeName gtn = new GenericsType.GenericsTypeName(genericsType.getName());
-                    if (genericsType.isPlaceholder() && genericsTypeMap.containsKey(gtn)) {
-                        copyTypes[i] = genericsTypeMap.get(gtn);
-                    } else {
-                        copyTypes[i] = genericsType;
-                    }
+        if (source.equals(target)) {
+            return source;
+        }
+        if (target.isInterface() ? source.implementsInterface(target) : source.isDerivedFrom(target)) {
+            ClassNode sc;
+            do {
+                sc = getNextSuperClass(source, target);
+                if (GenericsUtils.hasUnresolvedGenerics(sc)) {
+                    sc = GenericsUtils.correctToGenericsSpecRecurse(GenericsUtils.createGenericsSpec(source), sc);
                 }
-                superClass = superClass.getPlainNodeReference();
-                superClass.setGenericsTypes(copyTypes);
-            }
+            } while (!(source = sc).equals(target));
+
+            return sc;
         }
-        if (superClass!=null) return findGenericsTypeHolderForClass(superClass, type);
         return null;
     }
 
+    private static ClassNode upperBound(final GenericsType gt) {
+        if (gt.isWildcard()) {
+            ClassNode[] ub = gt.getUpperBounds();
+            if (ub != null) return ub[0];
+        }
+        return gt.getType();
+    }
+
     private static ClassNode lowestUpperBound(final ClassNode a, final ClassNode b, List<ClassNode> interfacesImplementedByA, List<ClassNode> interfacesImplementedByB) {
         // first test special cases
-        if (a==null || b==null) {
+        if (a == null || b == null) {
             // this is a corner case, you should not
             // compare two class nodes if one of them is null
             return null;
@@ -345,7 +313,7 @@ public class WideningCategories {
             // one of the objects is at the top of the hierarchy
             GenericsType[] gta = a.getGenericsTypes();
             GenericsType[] gtb = b.getGenericsTypes();
-            if (gta !=null && gtb !=null && gta.length==1 && gtb.length==1) {
+            if (gta != null && gtb != null && gta.length == 1 && gtb.length == 1) {
                 if (gta[0].getName().equals(gtb[0].getName())) {
                     return a;
                 }
@@ -383,9 +351,8 @@ public class WideningCategories {
             ClassNode ub = getUnwrapper(b);
             Integer pa = NUMBER_TYPES_PRECEDENCE.get(ua);
             Integer pb = NUMBER_TYPES_PRECEDENCE.get(ub);
-            if (pa!=null && pb!=null) {
-                if (pa<=pb) return a;
-                return b;
+            if (pa != null && pb != null) {
+                return pa <= pb ? a : b;
             }
         }
 
@@ -404,15 +371,15 @@ public class WideningCategories {
             // which are common
             ClassNode[] interfacesFromA = a.getInterfaces();
             ClassNode[] interfacesFromB = b.getInterfaces();
-            Set<ClassNode> common = new HashSet<ClassNode>();
+            Set<ClassNode> common = new HashSet<>();
             Collections.addAll(common, interfacesFromA);
-            Set<ClassNode> fromB = new HashSet<ClassNode>();
+            Set<ClassNode> fromB = new HashSet<>();
             Collections.addAll(fromB, interfacesFromB);
             common.retainAll(fromB);
 
-            if (common.size()==1) {
+            if (common.size() == 1) {
                 return common.iterator().next();
-            } else if (common.size()>1) {
+            } else if (common.size() > 1) {
                 return buildTypeWithInterfaces(a, b, common);
             }
 
@@ -430,25 +397,25 @@ public class WideningCategories {
             // for a ClassNode. Therefore, even if b doesn't implement
             // interface a, a could "implement" other interfaces that b
             // implements too, so we must create a list of matching interfaces
-            List<ClassNode> matchingInterfaces = new LinkedList<ClassNode>();
+            List<ClassNode> matchingInterfaces = new LinkedList<>();
             extractMostSpecificImplementedInterfaces(b, a, matchingInterfaces);
             if (matchingInterfaces.isEmpty()) {
                 // no interface in common
                 return OBJECT_TYPE;
             }
-            if (matchingInterfaces.size()==1) {
+            if (matchingInterfaces.size() == 1) {
                 // a single match, which should be returned
                 return matchingInterfaces.get(0);
             }
-            return buildTypeWithInterfaces(a,b, matchingInterfaces);
+            return buildTypeWithInterfaces(a, b, matchingInterfaces);
         }
         // both classes do not represent interfaces
         if (a.equals(b)) {
-            return buildTypeWithInterfaces(a,b, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
+            return buildTypeWithInterfaces(a, b, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
         }
         // test if one class inherits from the other
         if (a.isDerivedFrom(b) || b.isDerivedFrom(a)) {
-            return buildTypeWithInterfaces(a,b, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
+            return buildTypeWithInterfaces(a, b, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
         }
 
         // Look at the super classes
@@ -456,17 +423,17 @@ public class WideningCategories {
         ClassNode sb = b.getUnresolvedSuperClass();
 
         // extract implemented interfaces before "going up"
-        Set<ClassNode> ifa = new HashSet<ClassNode>();
+        Set<ClassNode> ifa = new HashSet<>();
         extractInterfaces(a, ifa);
-        Set<ClassNode> ifb = new HashSet<ClassNode>();
+        Set<ClassNode> ifb = new HashSet<>();
         extractInterfaces(b, ifb);
-        interfacesImplementedByA = interfacesImplementedByA==null?new LinkedList<ClassNode>(ifa):interfacesImplementedByA;
-        interfacesImplementedByB = interfacesImplementedByB==null?new LinkedList<ClassNode>(ifb):interfacesImplementedByB;
+        interfacesImplementedByA = interfacesImplementedByA == null ? new LinkedList<>(ifa) : interfacesImplementedByA;
+        interfacesImplementedByB = interfacesImplementedByB == null ? new LinkedList<>(ifb) : interfacesImplementedByB;
 
         // check if no superclass is defined
         // meaning that we reached the top of the object hierarchy
-        if (sa==null || sb==null) return buildTypeWithInterfaces(OBJECT_TYPE, OBJECT_TYPE, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
-
+        if (sa == null || sb == null)
+            return buildTypeWithInterfaces(OBJECT_TYPE, OBJECT_TYPE, keepLowestCommonInterfaces(interfacesImplementedByA, interfacesImplementedByB));
 
         // if one superclass is derived (or equals) another
         // then it is the common super type
@@ -479,7 +446,7 @@ public class WideningCategories {
     }
 
     private static void extractInterfaces(final ClassNode node, final Set<ClassNode> interfaces) {
-        if (node==null) return;
+        if (node == null) return;
         Collections.addAll(interfaces, node.getInterfaces());
         extractInterfaces(node.getSuperClass(), interfaces);
     }
@@ -493,9 +460,9 @@ public class WideningCategories {
      */
     private static List<ClassNode> keepLowestCommonInterfaces(final List<ClassNode> fromA, final List<ClassNode> fromB) {
         if (fromA == null || fromB == null) return Collections.emptyList();
-        Set<ClassNode> common = new HashSet<ClassNode>(fromA);
+        Set<ClassNode> common = new HashSet<>(fromA);
         common.retainAll(fromB);
-        List<ClassNode> result = new ArrayList<ClassNode>(common.size());
+        List<ClassNode> result = new ArrayList<>(common.size());
         for (ClassNode classNode : common) {
             addMostSpecificInterface(classNode, result);
         }
@@ -504,9 +471,8 @@ public class WideningCategories {
 
     private static void addMostSpecificInterface(final ClassNode interfaceNode, final List<ClassNode> nodes) {
         if (nodes.isEmpty()) nodes.add(interfaceNode);
-        for (int i = 0, nodesSize = nodes.size(); i < nodesSize; i++) {
-            final ClassNode node = nodes.get(i);
-            if (node.equals(interfaceNode)||node.implementsInterface(interfaceNode)) {
+        for (int i = 0, n = nodes.size(); i < n; i += 1) { ClassNode node = nodes.get(i);
+            if (node.equals(interfaceNode) || node.implementsInterface(interfaceNode)) {
                 // a more specific interface exists in the list, keep it
                 return;
             }
@@ -527,7 +493,7 @@ public class WideningCategories {
             for (ClassNode interfaceNode : interfaces) {
                 if (type.implementsInterface(interfaceNode)) result.add(interfaceNode);
             }
-            if (result.isEmpty() && interfaces.length>0) {
+            if (result.isEmpty() && interfaces.length > 0) {
                 // none if the direct interfaces match, but we must check "upper" in the hierarchy
                 for (ClassNode interfaceNode : interfaces) {
                     extractMostSpecificImplementedInterfaces(type, interfaceNode, result);
@@ -545,49 +511,32 @@ public class WideningCategories {
      * @return the class node representing the lowest upper bound
      */
     private static ClassNode buildTypeWithInterfaces(final ClassNode baseType1, final ClassNode baseType2, final Collection<ClassNode> interfaces) {
-        boolean noInterface = interfaces.isEmpty();
-        if (noInterface) {
-            if (baseType1.equals(baseType2)) return baseType1;
-            if (baseType1.isDerivedFrom(baseType2)) return baseType2;
+        if (interfaces.isEmpty()) {
             if (baseType2.isDerivedFrom(baseType1)) return baseType1;
+            if (baseType1.isDerivedFrom(baseType2)) return baseType2;
         }
-        if (OBJECT_TYPE.equals(baseType1) && OBJECT_TYPE.equals(baseType2) && interfaces.size()==1) {
-            if (interfaces instanceof List) {
-                return ((List<ClassNode>) interfaces).get(0);
-            }
-            return interfaces.iterator().next();
-        }
-        LowestUpperBoundClassNode type;
-        ClassNode superClass;
-        String name;
+
+        String name; ClassNode superClass;
         if (baseType1.equals(baseType2)) {
-            if (OBJECT_TYPE.equals(baseType1)) {
-                superClass = baseType1;
-                name = "Virtual$Object";
-            } else {
-                superClass = baseType1;
-                name = "Virtual$"+baseType1.getName();
-            }
+            name = "Virtual$" + baseType1.getName();
+            superClass = baseType1;
         } else {
-            superClass = OBJECT_TYPE.getPlainNodeReference();
+            name = "CommonAssignOf$" + baseType1.getName() + "$" + baseType2.getName();
             if (baseType1.isDerivedFrom(baseType2)) {
                 superClass = baseType2;
             } else if (baseType2.isDerivedFrom(baseType1)) {
                 superClass = baseType1;
-            }
-            name = "CommonAssignOf$"+baseType1.getName()+"$"+baseType2.getName();
-        }
-        Iterator<ClassNode> itcn = interfaces.iterator();
-        while (itcn.hasNext()) {
-            ClassNode next = itcn.next();
-            if (superClass.isDerivedFrom(next) || superClass.implementsInterface(next)) {
-                itcn.remove();
+            } else {
+                superClass = OBJECT_TYPE;
             }
         }
-        ClassNode[] interfaceArray = interfaces.toArray(ClassNode.EMPTY_ARRAY);
-        Arrays.sort(interfaceArray, INTERFACE_CLASSNODE_COMPARATOR);
-        type = new LowestUpperBoundClassNode(name, superClass, interfaceArray);
-        return type;
+
+        interfaces.removeIf(i -> superClass.equals(i) || superClass.implementsInterface(i));
+
+        int nInterfaces = interfaces.size();
+        if (nInterfaces == 0) return superClass;
+        if (nInterfaces == 1 && isObjectType(superClass)) return interfaces.iterator().next();
+        return new LowestUpperBoundClassNode(name, superClass, interfaces.toArray(ClassNode.EMPTY_ARRAY));
     }
 
     /**
@@ -602,28 +551,31 @@ public class WideningCategories {
      *
      */
     public static class LowestUpperBoundClassNode extends ClassNode {
-        private static final Comparator<ClassNode> CLASS_NODE_COMPARATOR = (cn1, cn2) -> {
-            String n1 = cn1 instanceof LowestUpperBoundClassNode?((LowestUpperBoundClassNode)cn1).name:cn1.getName();
-            String n2 = cn2 instanceof LowestUpperBoundClassNode?((LowestUpperBoundClassNode)cn2).name:cn2.getName();
-            return n1.compareTo(n2);
-        };
-        private final ClassNode compileTimeClassNode;
         private final String name;
         private final String text;
-
         private final ClassNode upper;
         private final ClassNode[] interfaces;
+        private final ClassNode compileTimeClassNode;
 
         public LowestUpperBoundClassNode(final String name, final ClassNode upper, final ClassNode... interfaces) {
-            super(name, ACC_PUBLIC|ACC_FINAL, upper, interfaces, null);
+            super(name, ACC_PUBLIC | ACC_FINAL, upper, interfaces, null);
+            this.name = name;
             this.upper = upper;
             this.interfaces = interfaces;
-            boolean usesGenerics;
-            Arrays.sort(interfaces, CLASS_NODE_COMPARATOR);
+            Arrays.sort(interfaces, (cn1, cn2) -> {
+                String n1 = cn1 instanceof LowestUpperBoundClassNode ? ((LowestUpperBoundClassNode) cn1).name : cn1.getName();
+                String n2 = cn2 instanceof LowestUpperBoundClassNode ? ((LowestUpperBoundClassNode) cn2).name : cn2.getName();
+                return n1.compareTo(n2);
+            });
             compileTimeClassNode = isObjectType(upper) && interfaces.length > 0 ? interfaces[0] : upper;
-            this.name = name;
-            usesGenerics = upper.isUsingGenerics();
-            List<GenericsType[]> genericsTypesList = new LinkedList<>();
+
+            StringJoiner sj = new StringJoiner(" or "/*, "(", ")"*/);
+            if (!isObjectType(upper)) sj.add(upper.getText());
+            for (ClassNode i: interfaces) sj.add(i.getText());
+            this.text = sj.toString();
+
+            boolean usesGenerics = upper.isUsingGenerics();
+            List<GenericsType[]> genericsTypesList = new ArrayList<>();
             genericsTypesList.add(upper.getGenericsTypes());
             for (ClassNode anInterface : interfaces) {
                 usesGenerics |= anInterface.isUsingGenerics();
@@ -635,23 +587,14 @@ public class WideningCategories {
             }
             setUsingGenerics(usesGenerics);
             if (usesGenerics) {
-                List<GenericsType> asArrayList = new ArrayList<>();
-                for (GenericsType[] genericsTypes : genericsTypesList) {
-                    if (genericsTypes!=null) {
-                        Collections.addAll(asArrayList, genericsTypes);
+                List<GenericsType> flatList = new ArrayList<>();
+                for (GenericsType[] gts : genericsTypesList) {
+                    if (gts != null) {
+                        Collections.addAll(flatList, gts);
                     }
                 }
-                setGenericsTypes(asArrayList.toArray(GenericsType.EMPTY_ARRAY));
+                setGenericsTypes(flatList.toArray(GenericsType.EMPTY_ARRAY));
             }
-            StringBuilder sb = new StringBuilder();
-            if (!isObjectType(upper)) sb.append(upper.getName());
-            for (ClassNode anInterface : interfaces) {
-                if (sb.length()>0) {
-                    sb.append(" or ");
-                }
-                sb.append(anInterface.getName());
-            }
-            this.text = sb.toString();
         }
 
         public String getLubName() {
@@ -696,14 +639,11 @@ public class WideningCategories {
 
         @Override
         public ClassNode getPlainNodeReference() {
-            ClassNode[] intf = interfaces==null?null:new ClassNode[interfaces.length];
-            if (intf!=null) {
-                for (int i = 0; i < interfaces.length; i++) {
-                    intf[i] = interfaces[i].getPlainNodeReference();
-                }
+            ClassNode[] faces = interfaces.clone();
+            for (int i = 0; i < interfaces.length; i += 1) {
+                faces[i] = interfaces[i].getPlainNodeReference();
             }
-            LowestUpperBoundClassNode plain = new LowestUpperBoundClassNode(name, upper.getPlainNodeReference(), intf);
-            return plain;
+            return new LowestUpperBoundClassNode(name, upper.getPlainNodeReference(), faces);
         }
     }
 
diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index 8de032e..94f4ce4 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -898,12 +898,12 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
     // GROOVY-10002
     void testCollectionTypesInitializedByListLiteral3() {
         shouldFailWithMessages '''
-            Set<String> set = [1,2,3]
-        ''', 'Cannot assign java.util.LinkedHashSet<java.lang.Integer> to: java.util.Set<java.lang.String>'
+            List<String> list = ['a','b',3]
+        ''', 'Cannot assign java.util.ArrayList<java.io.Serializable'
 
         shouldFailWithMessages '''
-            List<String> list = ['a','b',3]
-        ''', 'Cannot assign java.util.ArrayList<java.io.Serializable<? extends java.lang.Object>> to: java.util.List<java.lang.String>'
+            Set<String> set = [1,2,3]
+        ''', 'Cannot assign java.util.LinkedHashSet<java.lang.Integer> to: java.util.Set<java.lang.String>'
 
         shouldFailWithMessages '''
             Iterable<String> iter = [1,2,3]
@@ -914,16 +914,16 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot assign java.util.ArrayList<java.lang.Integer> to: java.util.Collection<java.lang.String>'
 
         shouldFailWithMessages '''
-            Deque<String> deque = [""]
-        ''', 'Cannot assign value of type java.util.List<java.lang.String> to variable of type java.util.Deque<java.lang.String>'
-
-        shouldFailWithMessages '''
             Deque<String> deque = []
         ''', 'Cannot assign value of type java.util.List<E> to variable of type java.util.Deque<java.lang.String>'
 
         shouldFailWithMessages '''
             Queue<String> queue = []
         ''', 'Cannot assign value of type java.util.List<E> to variable of type java.util.Queue<java.lang.String>'
+
+        shouldFailWithMessages '''
+            Deque<String> deque = [""]
+        ''', 'Cannot assign value of type java.util.List<java.lang.String> to variable of type java.util.Deque<java.lang.String>'
     }
 
     // GROOVY-7128