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


The following commit(s) were added to refs/heads/master by this push:
     new a416594551 GROOVY-9415: STC: support `Type[i]` when class provides a 
static `getAt`
a416594551 is described below

commit a4165945514318a9d60bcb60346d5d1a91bfe253
Author: Eric Milles <[email protected]>
AuthorDate: Mon Aug 15 12:29:51 2022 -0500

    GROOVY-9415: STC: support `Type[i]` when class provides a static `getAt`
---
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java | 22 +++++++---------------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 12 +++++-------
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 11 +++++++++++
 3 files changed, 23 insertions(+), 22 deletions(-)

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 7ddcc1496f..c77ee7d05c 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
@@ -74,6 +74,7 @@ import static 
org.codehaus.groovy.ast.ClassHelper.isBigDecimalType;
 import static org.codehaus.groovy.ast.ClassHelper.isBigIntegerType;
 import static org.codehaus.groovy.ast.ClassHelper.isClassType;
 import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
+import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveBoolean;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
 import static org.codehaus.groovy.ast.ClassHelper.isStringType;
@@ -92,7 +93,6 @@ import static 
org.codehaus.groovy.ast.tools.GeneralUtils.propX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.chooseBestMethod;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsByNameAndArguments;
-import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isClassClassNodeWrappingConcreteType;
 import static org.objectweb.asm.Opcodes.AALOAD;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
@@ -604,7 +604,7 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
                 "this error and file a bug report at 
https://issues.apache.org/jira/browse/GROOVY";);
     }
 
-    private boolean trySubscript(final Expression receiver, final String 
message, final Expression arguments, ClassNode rType, final ClassNode aType, 
boolean safe) {
+    private boolean trySubscript(final Expression receiver, final String 
message, final Expression arguments, final ClassNode rType, final ClassNode 
aType, final boolean safe) {
         if (getWrapper(rType).isDerivedFrom(Number_TYPE)
                 && getWrapper(aType).isDerivedFrom(Number_TYPE)) {
             if ("plus".equals(message) || "minus".equals(message) || 
"multiply".equals(message) || "div".equals(message)) {
@@ -627,9 +627,9 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
                 return true;
             } else {
                 // check if a getAt method can be found on the receiver
-                ClassNode current = rType;
+                ClassNode current = 
isClassClassNodeWrappingConcreteType(rType) ? 
rType.getGenericsTypes()[0].getType() : rType;
                 MethodNode getAtNode = null;
-                while (current != null && getAtNode == null) {
+                while (current != null && !isObjectType(current) && getAtNode 
== null) {
                     getAtNode = current.getDeclaredMethod("getAt", new 
Parameter[]{new Parameter(aType, "index")});
                     if (getAtNode == null) {
                         getAtNode = getCompatibleMethod(current, "getAt", 
aType);
@@ -657,18 +657,10 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
                     return true;
                 }
 
-                // make sure Map#getAt() and List#getAt handled with the 
bracket syntax are properly compiled
+                // make sure Map#getAt and List#getAt handled with the bracket 
syntax are properly compiled
                 ClassNode[] args = {aType};
-                boolean acceptAnyMethod =
-                        MAP_TYPE.equals(rType) || 
rType.implementsInterface(MAP_TYPE)
-                        || LIST_TYPE.equals(rType) || 
rType.implementsInterface(LIST_TYPE);
                 List<MethodNode> nodes = 
findDGMMethodsByNameAndArguments(controller.getSourceUnit().getClassLoader(), 
rType, message, args);
-                if (nodes.isEmpty()) {
-                    // retry with raw types
-                    rType = rType.getPlainNodeReference();
-                    nodes = 
findDGMMethodsByNameAndArguments(controller.getSourceUnit().getClassLoader(), 
rType, message, args);
-                }
-                if (nodes.size() == 1 || (nodes.size() > 1 && 
acceptAnyMethod)) {
+                if (nodes.size() == 1 || (nodes.size() > 1 && 
(isOrImplements(rType, MAP_TYPE) || isOrImplements(rType, LIST_TYPE)))) {
                     MethodCallExpression call = callX(receiver, message, 
arguments);
                     call.setImplicitThis(false);
                     call.setMethodTarget(nodes.get(0));
@@ -677,7 +669,7 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter {
                     call.visit(controller.getAcg());
                     return true;
                 }
-                if (implementsInterfaceOrIsSubclassOf(rType, MAP_TYPE)) {
+                if (isOrImplements(rType, MAP_TYPE)) {
                     // fallback to Map#get
                     MethodCallExpression call = callX(receiver, "get", 
arguments);
                     call.setImplicitThis(false);
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 9c1a3b92a7..3f7535535c 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4519,15 +4519,13 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
         }
 
         if (isArrayOp(op)) {
-            // using getPNR() to ignore generics at this point
-            // and a different binary expression not to pollute the AST
-            BinaryExpression newExpr = binX(leftExpression, 
expr.getOperation(), rightExpression);
-            newExpr.setSourcePosition(expr);
-            MethodNode method = findMethodOrFail(newExpr, 
left.getPlainNodeReference(), "getAt", right.getPlainNodeReference());
-            if (method != null && implementsInterfaceOrIsSubclassOf(right, 
RANGE_TYPE)) {
+            Expression copy = binX(leftExpression, expr.getOperation(), 
rightExpression);
+            copy.setSourcePosition(expr); // do not propagate 
BINARY_EXP_TARGET, etc.
+            MethodNode method = findMethodOrFail(copy, left, "getAt", 
rightRedirect);
+            if (method != null && 
!isNumberCategory(getWrapper(rightRedirect))) {
                 return inferReturnTypeGenerics(left, method, rightExpression);
             }
-            return method != null ? inferComponentType(left, right) : null;
+            return inferComponentType(left, right);
         }
 
         String operationName = getOperationName(op);
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy 
b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index 591a31d724..99d718cfb4 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -934,6 +934,17 @@ Printer
         '''
     }
 
+    // GROOVY-9415
+    void testStaticGetAtAndSquareBracketIndexing() {
+        assertScript '''
+            class C9415 {
+                static <T> T getAt(T t) { t }
+            }
+            def result = C9415[1] // Cannot find matching method 
Class#getAt(int)
+            assert result == 1
+        '''
+    }
+
     // GROOVY-9463
     void testMethodPointerUnknownReference() {
         shouldFailWithMessages '''

Reply via email to