Share your thoughts in the 2021 Clojure Community Survey!

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

+1 vote
in Compiler by
retagged by

Getting a verifier error:

Syntax error (VerifyError) compiling new at (bug.clj:8:1).
Operand stack underflow

Minimal repro:

deps.edn

{:paths ["."]}

IBad.java

public interface IBad {
    public void put(Object key, Object value);
    public void onbad(Object thing);
}

Compile:

javac IBad.java

clj at a command line:

 clj
Clojure 1.10.1
user=> (import IBad)
IBad

user=> (defrecord Y [y]
  IBad
  (onbad [_ _] :bad))

Syntax error (VerifyError) compiling new at (REPL:1:1).
Operand stack underflow
Exception Details:
  Location:
    user/Y.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn
  Reason:
    Attempt to pop empty stack.
  Current Frame:
    bci: @8
    flags: { }
    locals: { 'user/Y', 'java/lang/Object', 'java/lang/Object' }
    stack: { }
  Bytecode:
    0000000: 2a2b 2cb9 0177 0300 b0

user=> *e
#error {
 :cause "Operand stack underflow\nException Details:\n  Location:\n    user/Y.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'user/Y', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 0177 0300 b0                 \n"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling new at (1:1)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 1, :source "NO_SOURCE_PATH", :symbol new}
   :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 7115]}
  {:type java.lang.VerifyError
   :message "Operand stack underflow\nException Details:\n  Location:\n    user/Y.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @8: areturn\n  Reason:\n    Attempt to pop empty stack.\n  Current Frame:\n    bci: @8\n    flags: { }\n    locals: { 'user/Y', 'java/lang/Object', 'java/lang/Object' }\n    stack: { }\n  Bytecode:\n    0000000: 2a2b 2cb9 0177 0300 b0                 \n"
   :at [java.lang.Class getDeclaredConstructors0 "Class.java" -2]}]
 :trace
 [[java.lang.Class getDeclaredConstructors0 "Class.java" -2]
  [java.lang.Class privateGetDeclaredConstructors "Class.java" 3138]
  [java.lang.Class getConstructors "Class.java" 1944]
  [clojure.lang.Compiler$NewExpr <init> "Compiler.java" 2575]
  [clojure.lang.Compiler$NewExpr$Parser parse "Compiler.java" 2667]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7105]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7095]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler access$300 "Compiler.java" 38]
  [clojure.lang.Compiler$DefExpr$Parser parse "Compiler.java" 596]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7095]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6118]
  [clojure.lang.Compiler$LetExpr$Parser parse "Compiler.java" 6436]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7107]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7105]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler eval "Compiler.java" 7174]
  [clojure.lang.Compiler eval "Compiler.java" 7132]
  [clojure.core$eval invokeStatic "core.clj" 3214]
  [clojure.core$eval invoke "core.clj" 3210]
  [clojure.main$repl$read_eval_print__9086$fn__9089 invoke "main.clj" 437]
  [clojure.main$repl$read_eval_print__9086 invoke "main.clj" 437]
  [clojure.main$repl$fn__9095 invoke "main.clj" 458]
  [clojure.main$repl invokeStatic "main.clj" 458]
  [clojure.main$repl_opt invokeStatic "main.clj" 522]
  [clojure.main$main invokeStatic "main.clj" 667]
  [clojure.main$main doInvoke "main.clj" 616]
  [clojure.lang.RestFn invoke "RestFn.java" 397]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.RestFn applyTo "RestFn.java" 132]
  [clojure.lang.Var applyTo "Var.java" 705]
  [clojure.main main "main.java" 40]]}
user=>

I tried to recreate using just protocols and got no luck.

And an extra datapoint in case it sheds more light, using deftype succeeds

(deftype Y [y] IBad (onbad [_ _] :bad))
user.Y

2 Answers

+1 vote
by
selected by
by
I also tried to recreate using `defprotocol` and `definterface`. couldn't get a similar error. Not sure if that adds helpful context to the minimal repro or not.
0 votes
by

Wonder if IBad/put is clobbering the java.util.Map interface method, which defrecord implements by default (just throws an unsupported operation exception).

That would explain why deftype doesn't fail.

...