Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
Description
The spread-safe operator – aka a*.b or a*.b(c) – has some differences and inefficiencies.
- When the receiver is null, the expression produces null for dynamic mode and an empty list for static compilation. Can this difference be safely resolved?
- When the method return type is void, there is no need for a list to collect up nulls. This is producing "Useless object stored in variable var$1" warnings from SpotBugs. The only benefit of this is the ability to detect the number of elements.
- The SC bytecode has a redundant null test in it. Since a for loop is also null-safe, guarding the loop bytecode by a null check is producing "Redundant check for null" warnings from SpotBugs. NOTE: If (1) above is changed in the SC classgen, the null check may not be redundant as it would guard list construction.
For reference, object*.method(arguments) is written by the static compiler like this:
def result = new ArrayList() if (object != null) { for (Inferred element : object) { // also null-safe result.add(element?.method(arguments) } } result
And the dynamic impl: https://github.com/apache/groovy/blob/f46103d31b7574ce883ff3b6c01fa8a412f225be/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java#L189