2 odd cases - no-check and ann-record in a macro

25 views
Skip to first unread message

Steven Benjamin

unread,
Aug 13, 2015, 6:13:44 PM8/13/15
to core.typed
I've found two odd cases. The first seems like a bug :

In trying to annotate a multi-ariadic function I had some difficulty
digging up the syntax. (all of these examples came from working with
quartzite , a clojure wrapper around the Quartz library).

My incorrect annotation looked like this (The "Fn" should be "IFn" -icore-typed reports that "First argument to TApp must be TFn, actual: Fn").:

(t/ann loaded-triggers (t/Fn [ -> TriggerReport] [String -> TriggerReport]))
(defn loaded-triggers"
  ([] (loaded-triggers ""))
  ([triggerGroupName] ... ))


When I was first working with this I had the annotation marked as
:no-check.  What was surprising was that with no-check on core-typed
seems to accept what looks like a syntax error.

Second issue - I've run into a typing puzzle I cannot figure out how to solve, also related to the same library.

Quartz defines a Job interface  Job that just defines an execute function. The quartzite library defines a macro,
defjob, that provides a wrapper for this:

(defmacro defjob
 
[jtype args & body]
 
`(defrecord ~jtype []
      org.quartz.Job
     (execute [this ~@args]



I can't see how to annotate this, as it seems to refer to the macro
expansion (?) e.g.

(t/ann-record ReportJob [execute :- [t/Any JobExecutionContext]])
(defjob MyJob [^JobExecutionContext ctx] ... body that will run in job execute)


gives:
deftype MyJob fields do not match annotation.  Expected: [execute], Actual: [__meta __extmap]

I'd be happy to mark this as no-check but I can't even really
understand what it's supposed to be.

Any suggestions appreciated. 

Thanks,
Steve Benjamin

Ambrose Bonnaire-Sergeant

unread,
Aug 13, 2015, 11:18:38 PM8/13/15
to core.typed
On Fri, Aug 14, 2015 at 6:13 AM, Steven Benjamin <st...@flow.net> wrote:
I've found two odd cases. The first seems like a bug :

In trying to annotate a multi-ariadic function I had some difficulty
digging up the syntax. (all of these examples came from working with
quartzite , a clojure wrapper around the Quartz library).

My incorrect annotation looked like this (The "Fn" should be "IFn" -icore-typed reports that "First argument to TApp must be TFn, actual: Fn").:

(t/ann loaded-triggers (t/Fn [ -> TriggerReport] [String -> TriggerReport]))
(defn loaded-triggers"
  ([] (loaded-triggers ""))
  ([triggerGroupName] ... ))


When I was first working with this I had the annotation marked as
:no-check.  What was surprising was that with no-check on core-typed
seems to accept what looks like a syntax error.

This will eventually be caught if loaded-triggers is ever invoked. Leaving this as is for now.
 

Second issue - I've run into a typing puzzle I cannot figure out how to solve, also related to the same library.

Quartz defines a Job interface  Job that just defines an execute function. The quartzite library defines a macro,
defjob, that provides a wrapper for this:

(defmacro defjob
 
[jtype args & body]
 
`(defrecord ~jtype []
      org.quartz.Job
     (execute [this ~@args]



I can't see how to annotate this, as it seems to refer to the macro
expansion (?) e.g.

(t/ann-record ReportJob [execute :- [t/Any JobExecutionContext]])
(defjob MyJob [^JobExecutionContext ctx] ... body that will run in job execute)


gives:
deftype MyJob fields do not match annotation.  Expected: [execute], Actual: [__meta __extmap]

You should be able to just annotate the defrecord like so.
 
(t/ann-record MyJob []])

(defjob MyJob [^JobExecutionContext ctx] ... body that will run in job execute)

Always think in terms of the final macroexpansion when trying to type check something.

Steven Benjamin

unread,
Aug 17, 2015, 11:08:10 AM8/17/15
to core.typed
Thanks very much for the response and the help. Still stuck, this might easily be the result of things I'm missing about the core language itself. But in any case, here's the results I get when I put in the fixes you suggest:

Currently, the code I had looked like this:

;; (t/ann-record ReportJob [])  ;;  line 1

(defjob ReportJob [ctx]  ;;  line 2

In this state, I just get a type error :  
deftype flow.mqtt.scheduler.ReportJob must have corresponding annotation. See ann-datatype and ann-record

changing (2) to

(defjob ReportJob [^JobExecutionContext ctx]

Gives the error:
   Error compiling: flow/mqtt/scheduler.clj:94:1
                 
Compiler.java: 6730  clojure.lang.Compiler/analyzeSeq
                 
Compiler.java: 6524  clojure.lang.Compiler/analyze
                 
Compiler.java: 6485  clojure.lang.Compiler/analyze
1. Caused by java.lang.IllegalArgumentException
   
Mismatched return type: execute, expected: void, had:
   java
.lang.Object
                 
Compiler.java: 8068  clojure.lang.Compiler$NewInstanceMethod/parse
                 
Compiler.java: 7642  clojure.lang.Compiler$NewInstanceExpr/build
...

uncommenting the annotation @line1 gives
 
1. Unhandled java.lang.AssertionError
   
Pre-condition failure: A lexical environment l, props is a list of
   known propositions
Assert failed: (lex-env? l)

Tried some other variations with equally confusing results. Not sure how/why I'm getting an error just pushing the type hint into the macro, but possibly this is why I can't properly type it? Macroexpanding the (type-hinted) version gave me no useful clues (this in particular might be due to my lack of familiarity with what's going on - I'd think if the type hint were breaking it would show up in the macroexpand but that's not the case). 

In any case, thanks for checking.

Reply all
Reply to author
Forward
0 new messages