Welcome! Please see the About page for a little more info on how this works.

+1 vote
ago in Java Interop by
retagged ago by

Has anyone else noticed a lot of Syntax error (NullPointerException) when using the new Class/.instanceMethod syntax? Specifically whenever I forget the first argument like

(fn [] (String/.length))

gets

#error{:cause "Cannot invoke \"clojure.lang.Compiler$Expr.emit(clojure.lang.Compiler$C, clojure.lang.Compiler$ObjExpr, clojure.asm.commons.GeneratorAdapter)\" because \"this.target\" is null",
       :via [{:type clojure.lang.Compiler$CompilerException,
              :message "Syntax error compiling fn* at (/private/var/folders/cr/wpw7hgnx0jj9m33g28rtbpzc0000gn/T/form-init4871175438924650637.clj:1:1).",
              :data #:clojure.error{:phase :compile-syntax-check,
                                    :line 1,
                                    :column 1,
                                    :source "/private/var/folders/cr/wpw7hgnx0jj9m33g28rtbpzc0000gn/T/form-init4871175438924650637.clj",
                                    :symbol fn*},
              :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 7677]}
             {:type java.lang.NullPointerException,
              :message "Cannot invoke \"clojure.lang.Compiler$Expr.emit(clojure.lang.Compiler$C, clojure.lang.Compiler$ObjExpr, clojure.asm.commons.GeneratorAdapter)\" because \"this.target\" is null",
              :at [clojure.lang.Compiler$InstanceMethodExpr emit "Compiler.java" 2060]}],
       :trace [[clojure.lang.Compiler$InstanceMethodExpr emit "Compiler.java" 2060]
               [clojure.lang.Compiler$BodyExpr emit "Compiler.java" 6723]
               [clojure.lang.Compiler$FnMethod doEmit "Compiler.java" 6243]
               [clojure.lang.Compiler$FnMethod emit "Compiler.java" 6045]
               [clojure.lang.Compiler$FnExpr emitMethods "Compiler.java" 4500]
               [clojure.lang.Compiler$ObjExpr compile "Compiler.java" 5136]
               [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4662]
               [clojure.lang.Compiler analyzeSeq "Compiler.java" 7667]
               [clojure.lang.Compiler analyze "Compiler.java" 7360]
               [clojure.lang.Compiler analyze "Compiler.java" 7316]
               [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6683]
               [clojure.lang.Compiler$FnMethod parse "Compiler.java" 6022]
               [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4585]
               [clojure.lang.Compiler analyzeSeq "Compiler.java" 7667]
               [clojure.lang.Compiler analyze "Compiler.java" 7360]
               [clojure.lang.Compiler eval "Compiler.java" 7736]
               [clojure.lang.Compiler eval "Compiler.java" 7694]
               [clojure.core$eval invokeStatic "core.clj" 3232]
               [clojure.core$eval invoke "core.clj" 3228]
               [nrepl.middleware.interruptible_eval$evaluate$fn__966$fn__967 invoke "interruptible_eval.clj" 87]
               [clojure.lang.AFn applyToHelper "AFn.java" 152]
               [clojure.lang.AFn applyTo "AFn.java" 144]
               [clojure.core$apply invokeStatic "core.clj" 667]
               [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1990]
               [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1990]
               [clojure.lang.RestFn invoke "RestFn.java" 428]
               [nrepl.middleware.interruptible_eval$evaluate$fn__966 invoke "interruptible_eval.clj" 87]
               [clojure.main$repl$read_eval_print__9248$fn__9251 invoke "main.clj" 437]
               [clojure.main$repl$read_eval_print__9248 invoke "main.clj" 437]
               [clojure.main$repl$fn__9257 invoke "main.clj" 459]
               [clojure.main$repl invokeStatic "main.clj" 459]
               [clojure.main$repl doInvoke "main.clj" 368]
               [clojure.lang.RestFn invoke "RestFn.java" 1526]
               [nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 84]
               [nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
               [nrepl.middleware.interruptible_eval$interruptible_eval$fn__997$fn__1001
                invoke
                "interruptible_eval.clj"
                152]
               [clojure.lang.AFn run "AFn.java" 22]
               [nrepl.middleware.session$session_exec$main_loop__1065$fn__1069 invoke "session.clj" 202]
               [nrepl.middleware.session$session_exec$main_loop__1065 invoke "session.clj" 201]
               [clojure.lang.AFn run "AFn.java" 22]
               [java.lang.Thread run "Thread.java" 1447]]}
ago by
To do some preliminary digging, looks like:

* `InvokeExpr.parse` determines the call is a `QualifiedMethodExpr`.
* `InvokeExpr.parse` calls into `InvokeExpr.toHostExpr` with an empty vector of `args`.
* `InvokeExpr.toHostExpr` constructs a new `InstanceMethodExpr` with target as `RT.first(args)` (which is null)
* `InstanceMethodExpr.emit` assumes that `target` is non-null, calling `target.emit(C.EXPRESSION, objx, gen);` in both branches.
ago by
Clojure has always thrown an error in such cases:

    (fn [] (.length))
    Syntax error (IllegalArgumentException) compiling at (REPL:1:8).
    Malformed member expression, expecting (.member target ...)

That said, they were not NPEs. I assume that you'd prefer a more informative error like above?
ago by
I'm not the original asker, but yes I would.

1 Answer

+1 vote
ago by
...