Clojure

NullPointerException on function with primitive result declaration

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.6
  • Fix Version/s: None
  • Component/s: None

Description

The following minimal example shows the error:

(defn f ^double [])
(f)
=> NullPointerException

When decompiling the function `f` I found the following return expression:

return null.doubleValue();

This happened in a Java interop scenario where the called Java method had no return value but was in the return position of the primitive Clojure function.
The compiler should check for `null` on compilation.

Another example - calling a method with void return as the last expression fails in a similar way:

(defn f ^double [^SomeClassToAvoidRuntimeReflection obj, x, y]
  (.someMethod obj, x, y))
(f obj, x, y)
=> NullPointerException

Activity

Hide
Alex Miller added a comment -

What do you expect to happen in this case? You declared a function as returning a double but didn't return one.

Show
Alex Miller added a comment - What do you expect to happen in this case? You declared a function as returning a double but didn't return one.
Hide
Gunnar Völkel added a comment - - edited

Since this is only the minimal example the error is relatively easy to spot.
Consider the following small example with Java interop:

(defn f ^double [^SomeClassToAvoidRuntimeReflection obj, x, y]
  (.someMethod obj, x, y))
(f obj, x, y)
=> NullPointerException

In this example it is much harder to find the reason for the NPE because you'd first suspect `obj` to be `null`.

I expect a check in the compiler at the point where "return null.doubleValue();" is emitted, followed by an error message, e.g. "Primitive return value of type 'double' expected, but no value is returned.".

Show
Gunnar Völkel added a comment - - edited Since this is only the minimal example the error is relatively easy to spot. Consider the following small example with Java interop:
(defn f ^double [^SomeClassToAvoidRuntimeReflection obj, x, y]
  (.someMethod obj, x, y))
(f obj, x, y)
=> NullPointerException
In this example it is much harder to find the reason for the NPE because you'd first suspect `obj` to be `null`. I expect a check in the compiler at the point where "return null.doubleValue();" is emitted, followed by an error message, e.g. "Primitive return value of type 'double' expected, but no value is returned.".
Hide
Jozef Wagner added a comment -

Your second example seems perfectly OK to me, compiler should not report any error and NPE check must be at runtime.

Show
Jozef Wagner added a comment - Your second example seems perfectly OK to me, compiler should not report any error and NPE check must be at runtime.
Hide
Gunnar Völkel added a comment - - edited

@Jozef: No, you are wrong. The compiler infers via reflection at compile time that the called method does not return a value and emits "return null.doubleValue()". So this can and should be reported as explicit error at compile time. I added a typehint to make it clear that there is no runtime reflection involved.
You would be right, if the compiler emitted something like "return somevar.doubleValue();" because then at compile time there is no knowledge about a possible "null" value.

Show
Gunnar Völkel added a comment - - edited @Jozef: No, you are wrong. The compiler infers via reflection at compile time that the called method does not return a value and emits "return null.doubleValue()". So this can and should be reported as explicit error at compile time. I added a typehint to make it clear that there is no runtime reflection involved. You would be right, if the compiler emitted something like "return somevar.doubleValue();" because then at compile time there is no knowledge about a possible "null" value.
Hide
Andy Fingerhut added a comment -

Gunnar, in your example, is the method 'someMethod' declared to return void, or something else? Adding that info to your example might help clarify it.

Show
Andy Fingerhut added a comment - Gunnar, in your example, is the method 'someMethod' declared to return void, or something else? Adding that info to your example might help clarify it.
Hide
Jozef Wagner added a comment -

Gunnar, the second example was ambiguous and strayed away the discussion. Anyway, whether returning wrong type is through the native method or not, it is a user error in the first place. Right now it is reported at runtime. For me this ticket should be a minor enhancement instead of defect.

Show
Jozef Wagner added a comment - Gunnar, the second example was ambiguous and strayed away the discussion. Anyway, whether returning wrong type is through the native method or not, it is a user error in the first place. Right now it is reported at runtime. For me this ticket should be a minor enhancement instead of defect.
Hide
Gunnar Völkel added a comment - - edited

Yes, the reason is a user error. But one that is harder to debug than necessary.
Also, it is clearly a defect since emitting 'null.doubleValue()' can not be considered as a valid compilation.

Andy, yes 'someMethod' is declared to return void. I'd edit the original ticket text to add the example and the java method return value information, but it seems jira does not let me.

Show
Gunnar Völkel added a comment - - edited Yes, the reason is a user error. But one that is harder to debug than necessary. Also, it is clearly a defect since emitting 'null.doubleValue()' can not be considered as a valid compilation. Andy, yes 'someMethod' is declared to return void. I'd edit the original ticket text to add the example and the java method return value information, but it seems jira does not let me.
Hide
Alex Miller added a comment -

I added the second example (with clarifying void comment) to the description.

Show
Alex Miller added a comment - I added the second example (with clarifying void comment) to the description.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: