Oscar N created GROOVY-11629: -------------------------------- Summary: Redundant null check on @NullChecked parameter when iterating on it Key: GROOVY-11629 URL: https://issues.apache.org/jira/browse/GROOVY-11629 Project: Groovy Issue Type: Bug Affects Versions: 4.0.26, 3.0.24, 5.0.0-alpha-12 Reporter: Oscar N
When looping over a method parameter whose method is annotated with @NullCheck, an additional null check performed before iterating. Here's a minimal example, demonstrating the numbers parameter being checked for null twice: {code:groovy} import groovy.transform.CompileStatic import groovy.transform.NullCheck void main() { listNumbers([1, 2, 3]) } @CompileStatic @NullCheck void listNumbers(List<Number> numbers) { for (number in numbers) println number } {code} Decompiled Java representation of the bytecode: {code:java} public void listNumbers(List<Number> numbers) { if (numbers == null) { throw (Throwable)(new IllegalArgumentException("numbers cannot be null")); } else { Iterator var10000 = numbers != null ? numbers.iterator() : null; Object number = null; Iterator var4 = var10000; if (var4 != null) { while(var4.hasNext()) { number = var4.next(); DefaultGroovyMethods.println(this, number); Object var6 = null; } } } } {code} Bytecode: {code:java} // access flags 0x1 // signature (Ljava/util/List<Ljava/lang/Number;>;)V // declaration: void listNumbers(java.util.List<java.lang.Number>) public listNumbers(Ljava/util/List;)V L0 ALOAD 1 IFNONNULL L1 ICONST_1 GOTO L2 L1 ICONST_0 L2 IFEQ L3 NEW java/lang/IllegalArgumentException DUP LDC "numbers cannot be null" INVOKESPECIAL java/lang/IllegalArgumentException.<init> (Ljava/lang/String;)V CHECKCAST java/lang/Throwable ATHROW L3 LINENUMBER 11 L3 ALOAD 1 DUP ASTORE 2 IFNULL L4 ALOAD 2 INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; (itf) GOTO L5 L4 ACONST_NULL L5 ACONST_NULL ASTORE 3 L6 ASTORE 4 ALOAD 4 IFNULL L7 L8 ALOAD 4 INVOKEINTERFACE java/util/Iterator.hasNext ()Z (itf) IFEQ L7 ALOAD 4 INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object; (itf) ASTORE 3 L9 LINENUMBER 12 L9 ALOAD 0 ALOAD 3 INVOKESTATIC org/codehaus/groovy/runtime/DefaultGroovyMethods.println (Ljava/lang/Object;Ljava/lang/Object;)V ACONST_NULL POP GOTO L8 L7 LINENUMBER 13 L7 RETURN LOCALVARIABLE this LRedundantNullCheck; L0 L7 0 LOCALVARIABLE numbers Ljava/util/List; L0 L7 1 LOCALVARIABLE number Ljava/lang/Object; L6 L7 3 MAXSTACK = 3 MAXLOCALS = 5 {code} Note that this also happens in CompileDynamic mode. -- This message was sent by Atlassian Jira (v8.20.10#820010)