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

jonnybot pushed a commit to branch 
GROOVY-9526-regression-semantic-analysis-exception
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 24ab6a3a4b9e8b862f5bc3c46dd962ef6aaf97a1
Author: Jonny Carter <jcar...@adaptavist.com>
AuthorDate: Mon Jul 21 15:29:25 2025 -0500

    Fix generics handling error
    
    Under the hood, the root cause seemed to be this:
    
    Caused by: java.lang.UnsupportedOperationException
            at java.base/java.util.AbstractMap.put(AbstractMap.java:209)
            at 
org.codehaus.groovy.control.ResolveVisitor.resolveGenericsHeader(ResolveVisitor.java:1452)
            at 
org.codehaus.groovy.control.ResolveVisitor.resolveGenericsHeader(ResolveVisitor.java:1409)
    
    Based on a look in the debugger, without this change, the
    genericParameterNames field will be a Collections$EmptyMap, which is
    immutable and therefore doesn't support PUT operations.
---
 .../codehaus/groovy/control/ResolveVisitor.java    |  2 +-
 .../util/GroovyScriptEngineReloadingTest.groovy    | 33 ++++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java 
b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 383c0bffa7..33ec9c51e6 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -1279,7 +1279,7 @@ public class ResolveVisitor extends 
ClassCodeExpressionTransformer {
             if (!Modifier.isStatic(node.getModifiers()))
                 genericParameterNames.putAll(outerNames); // outer names 
visible
         } else {
-            genericParameterNames.clear(); // outer class: new generic 
namespace
+            genericParameterNames = new HashMap<>(); // outer class: new 
generic namespace
         }
         resolveGenericsHeader(node.getGenericsTypes());
         switch (phase) { // GROOVY-9866, GROOVY-10466
diff --git a/src/test/groovy/groovy/util/GroovyScriptEngineReloadingTest.groovy 
b/src/test/groovy/groovy/util/GroovyScriptEngineReloadingTest.groovy
index 660f4ddcf0..935d99abc8 100644
--- a/src/test/groovy/groovy/util/GroovyScriptEngineReloadingTest.groovy
+++ b/src/test/groovy/groovy/util/GroovyScriptEngineReloadingTest.groovy
@@ -182,6 +182,39 @@ final class GroovyScriptEngineReloadingTest {
 
     }
 
+    @Test
+    void testRecompilingWithGenericsAndConstants() {
+        MapFileSystem.instance.modFile('BaseClass.groovy', 'class BaseClass<T> 
{}', gse.@time)
+
+        def tertiaryClassText = '''
+            class NotGeneric {
+                /**
+                 * Not typed on purpose - if typed as String then NotGeneric 
is no longer a dependency of
+                 * ParameterisedClass for some reason...
+                 */
+                public static final Object CONSTANT = "not generic"
+            }
+        '''
+        MapFileSystem.instance.modFile('NotGeneric.groovy', tertiaryClassText, 
gse.@time)
+
+        def subClassText = '''
+            class SubClass extends BaseClass<String> {
+                public static final String CONSTANT = NotGeneric.CONSTANT
+            }
+        '''
+        MapFileSystem.instance.modFile('SubClass.groovy', subClassText, 
gse.@time)
+
+        MapFileSystem.instance.modFile('scriptUsingGeneric.groovy', 
'SubClass.CONSTANT', gse.@time)
+
+
+        gse.loadScriptByName('scriptUsingGeneric.groovy')
+        sleep 1000
+
+        // make a change to the sub-class so that it gets recompiled
+        MapFileSystem.instance.modFile('SubClass.groovy', subClassText + '\n', 
gse.@time)
+        gse.loadScriptByName('scriptUsingGeneric.groovy')
+    }
+
     @Test
     void testDeleteDependent() {
         sleep 10000

Reply via email to