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 2022/05/15 18:44:12 UTC
[groovy] branch master updated: GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`
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 855940b55c GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`
855940b55c is described below
commit 855940b55c51f5eb17bb9d33b86fe73be56b3d9c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 15 13:27:39 2022 -0500
GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`
---
src/main/groovy/groovy/grape/GrapeIvy.groovy | 6 +--
.../transform/stc/StaticTypeCheckingVisitor.java | 21 +++++----
.../groovy/transform/stc/ClosuresSTCTest.groovy | 6 +--
.../groovy/transform/stc/STCAssignmentTest.groovy | 35 ++++++++++-----
.../groovy/macro/matcher/ASTMatcher.groovy | 52 +++++++++++-----------
5 files changed, 65 insertions(+), 55 deletions(-)
diff --git a/src/main/groovy/groovy/grape/GrapeIvy.groovy b/src/main/groovy/groovy/grape/GrapeIvy.groovy
index 4afe525472..bfc00258f1 100644
--- a/src/main/groovy/groovy/grape/GrapeIvy.groovy
+++ b/src/main/groovy/groovy/grape/GrapeIvy.groovy
@@ -457,11 +457,11 @@ class GrapeIvy implements GrapeEngine {
if (report.getDownloadSize() && reportDownloads) {
System.err.println("Downloaded ${report.getDownloadSize() >> 10} Kbytes in ${report.getDownloadTime()}ms:\n ${report.getAllArtifactsReports()*.toString().join('\n ')}")
}
- md = report.getModuleDescriptor()
if (!args.preserveFiles) {
- cacheManager.getResolvedIvyFileInCache(md.getModuleRevisionId()).delete()
- cacheManager.getResolvedIvyPropertiesInCache(md.getModuleRevisionId()).delete()
+ def revision = report.getModuleDescriptor().getModuleRevisionId()
+ cacheManager.getResolvedIvyPropertiesInCache(revision).delete()
+ cacheManager.getResolvedIvyFileInCache(revision).delete()
}
report
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 aa97772762..cec013a9fc 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1073,15 +1073,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
protected ClassNode getOriginalDeclarationType(final Expression lhs) {
- if (lhs instanceof VariableExpression) {
- Variable var = findTargetVariable((VariableExpression) lhs);
- if (!(var instanceof DynamicVariable || var instanceof PropertyNode)) {
- return var.getOriginType();
- }
- } else if (lhs instanceof FieldExpression) {
- return ((FieldExpression) lhs).getField().getOriginType();
+ Variable var = null;
+ if (lhs instanceof FieldExpression) {
+ var = ((FieldExpression) lhs).getField();
+ } else if (lhs instanceof VariableExpression) {
+ var = findTargetVariable((VariableExpression) lhs);
}
- return getType(lhs);
+ return var != null && !(var instanceof DynamicVariable) ? var.getOriginType() : getType(lhs);
}
protected void inferDiamondType(final ConstructorCallExpression cce, final ClassNode lType) {
@@ -4300,11 +4298,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
protected void storeType(final Expression exp, ClassNode cn) {
- if (cn == UNKNOWN_PARAMETER_TYPE) {
- // this can happen for example when "null" is used in an assignment or a method parameter.
- // In that case, instead of storing the virtual type, we must "reset" type information
+ if (cn == UNKNOWN_PARAMETER_TYPE) { // null for assignment or parameter
+ // instead of storing an "unknown" type, reset the type information
// by determining the declaration type of the expression
cn = getOriginalDeclarationType(exp);
+ // GROOVY-10356, GROOVY-10623: "def"
+ if (isDynamicTyped(cn)) return;
}
if (cn != null && isPrimitiveType(cn)) {
if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) {
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index d922bb572a..b233142aa3 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -18,8 +18,6 @@
*/
package groovy.transform.stc
-import groovy.test.NotYetImplemented
-
/**
* Unit tests for static type checking : closures.
*/
@@ -375,7 +373,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
'Cannot find matching method A#m()'
}
- @NotYetImplemented // GROOVY-10356
+ // GROOVY-10356
void testClosureSharedVariable4() {
assertScript '''
interface A {
@@ -385,7 +383,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
def x = { ->
a = null
}
- a?.m() // A closure shared variable [a] has been assigned with various types and ...
+ a?.m()
'''
}
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index 2af80307e8..9064e5e225 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -1062,18 +1062,22 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
''', 'Inconvertible types: cannot cast java.lang.String[] to java.util.Set[]'
}
- // GROOVY-5535
+ // GROOVY-5535, GROOVY-10623
void testAssignToNullInsideIf() {
- assertScript '''
- Date test() {
- Date x = new Date()
- if (true) {
- x = null
+ ['Date', 'def', 'var'].each {
+ assertScript """
+ Date test() {
+ $it x = new Date()
+ if (true) {
+ x = null
+ Date y = x
+ }
+ Date z = x
+ return x
}
- x
- }
- assert test() == null
- '''
+ assert test() == null
+ """
+ }
}
// GROOVY-10294
@@ -1103,6 +1107,17 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10623
+ void testAssignToNullAfterInit() {
+ assertScript '''
+ class C {
+ }
+ def x = new C()
+ x = null
+ C c = x
+ '''
+ }
+
// GROOVY-5798
void testShouldNotThrowConversionError() {
assertScript '''
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
index 857c71212d..c2bd6a9480 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
@@ -75,17 +75,16 @@ import org.codehaus.groovy.macro.matcher.internal.MatchingConstraintsBuilder
@AutoFinal @CompileStatic
class ASTMatcher extends ContextualClassCodeVisitor {
- public static final String WILDCARD = "_"
+ public static final String WILDCARD = '_'
- private Object current = null
private boolean match = true
+ private Object current
private ASTMatcher() {
}
@Override
protected SourceUnit getSourceUnit() {
- return null
}
/**
@@ -230,7 +229,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
def nodeProps = node.properties
def curProps = cur.properties
if (nodeProps.size() == curProps.size()) {
- def iter = curProps.iterator()
+ Iterator<? extends ASTNode> iter = curProps.iterator()
// now let's visit the contents of the class
for (PropertyNode pn : nodeProps) {
doWithNode(pn, iter.next()) {
@@ -307,8 +306,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
void visitImports(ModuleNode node) {
if (node) {
doWithNode(node, current) {
- ModuleNode module = (ModuleNode) current
- def imports = module.imports
+ def imports = ((ModuleNode) current).imports
if (imports.size() == node.imports.size()) {
def iter = imports.iterator()
for (ImportNode importNode : node.imports) {
@@ -321,38 +319,38 @@ class ASTMatcher extends ContextualClassCodeVisitor {
failIfNot(false)
return
}
- imports = module.starImports
- if (imports.size() == node.starImports.size()) {
- def iter = imports.iterator()
- for (ImportNode importNode : node.starImports) {
- doWithNode(importNode, iter.next()) {
- visitAnnotations(importNode)
- importNode.visit(this)
+ def starImports = ((ModuleNode) current).starImports
+ if (starImports.size() == node.starImports.size()) {
+ def iter = starImports.iterator()
+ for (starImport in node.starImports) {
+ doWithNode(starImport, iter.next()) {
+ visitAnnotations(starImport)
+ starImport.visit(this)
}
}
} else {
failIfNot(false)
return
}
- imports = module.staticImports
- if (imports.size() == node.staticImports.size()) {
- def iter = imports.values().iterator()
- for (ImportNode importNode : node.staticImports.values()) {
- doWithNode(importNode, iter.next()) {
- visitAnnotations(importNode)
- importNode.visit(this)
+ def staticImports = ((ModuleNode) current).staticImports
+ if (staticImports.size() == node.staticImports.size()) {
+ def iter = staticImports.values().iterator()
+ for (staticImport in node.staticImports.values()) {
+ doWithNode(staticImport, iter.next()) {
+ visitAnnotations(staticImport)
+ staticImport.visit(this)
}
}
} else {
failIfNot(false)
}
- imports = module.staticStarImports
- if (imports.size() == node.staticStarImports.size()) {
- def iter = imports.values().iterator()
- for (ImportNode importNode : node.staticStarImports.values()) {
- doWithNode(importNode, iter.next()) {
- visitAnnotations(importNode)
- importNode.visit(this)
+ def staticStarImports = ((ModuleNode) current).staticStarImports
+ if (staticStarImports.size() == node.staticStarImports.size()) {
+ def iter = staticStarImports.values().iterator()
+ for (staticStarImport in node.staticStarImports.values()) {
+ doWithNode(staticStarImport, iter.next()) {
+ visitAnnotations(staticStarImport)
+ staticStarImport.visit(this)
}
}
} else {