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 '''