Martin Häusler created GROOVY-11563: ---------------------------------------
Summary: CompileStatic does not detect type mismatch on "+=" Key: GROOVY-11563 URL: https://issues.apache.org/jira/browse/GROOVY-11563 Project: Groovy Issue Type: Bug Components: Static compilation, Static Type Checker Affects Versions: 4.0.25 Reporter: Martin Häusler Hello, I'm using Groovy 4.0.25 on OpenJDK 21. I'm using static compilation. It seems like the static typechecker is unable to find type issues related to the "+=" operator. I have a full self-contained JUnit test for you below. In the test class, there are two test methods that check the output of the type checker. Please note that "<number> += <string>" compiles without problems (and it really should report an issue here), but "<number> = <number> + <string>" produces the expected compilation issue. {code:java} import groovy.lang.GroovyClassLoader; import groovy.transform.CompileStatic; import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.CompilerConfiguration; import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer; import org.codehaus.groovy.control.messages.Message; import org.codehaus.groovy.control.messages.WarningMessage; import org.junit.jupiter.api.Test; import java.util.List; import java.util.UUID; import static org.junit.jupiter.api.Assertions.fail; public class GroovyCompilerStandaloneExampleTest { @Test public void testWithPlusEquals() throws Exception { try { compileGroovy( "Number x = 0\n" + "x += \"hello\"" ); fail("No compile error!"); } catch (CompilationFailedException e) { // success! } } @Test public void testWithAssignment() throws Exception { try { compileGroovy( "Number x = 0\n" + "x = x + \"hello\"" ); fail("No compile error!"); } catch (CompilationFailedException e) { // success! } } private Class<?> compileGroovy(String source) throws Exception { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); CompilerConfiguration compilerConfig = createCompilerConfig(); try (GroovyClassLoader gcl = new GroovyClassLoader(classLoader, compilerConfig)) { List<? extends Class<?>> classes = compileInternal(compilerConfig, gcl, source); return classes.getFirst(); } } private CompilerConfiguration createCompilerConfig() { CompilerConfiguration config = new CompilerConfiguration(); config.setWarningLevel(WarningMessage.PARANOIA); config.addCompilationCustomizers( new ASTTransformationCustomizer(CompileStatic.class) ); return config; } private List<? extends Class<?>> compileInternal( CompilerConfiguration config, GroovyClassLoader gcl, String sourceCode ) throws Exception { CompilationUnit compilationUnit = new CompilationUnit(config, null, gcl); compilationUnit.addSource("script-" + UUID.randomUUID().toString(), sourceCode); compilationUnit.compile(); List<? extends Message> errors = compilationUnit.getErrorCollector().getErrors(); if (errors != null && !errors.isEmpty()) { fail("Groovy compilation has failed with " + errors.size() + " errors:\n" + String.join("\n - ", errors.toString())); } return compilationUnit.getClasses().stream().map(groovyClass -> { gcl.defineClass(groovyClass.getName(), groovyClass.getBytes()); try { return gcl.loadClass(groovyClass.getName()); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } }).toList(); } } {code} -- This message was sent by Atlassian Jira (v8.20.10#820010)