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)

Reply via email to