clojure.core.typed

This namespace contains typed wrapper macros, type aliases
and functions for type checking Clojure code. check-ns is the interface
for checking namespaces, cf for checking individual forms.

-ann

(-ann m)

-defalias

(-defalias m)

ann

macro

(ann varsym typesyn)
Annotate varsym with type. If unqualified, qualify in the current namespace.
If varsym has metadata {:no-check true}, ignore definitions of varsym 
while type checking. Supports namespace aliases and fully qualified namespaces
to annotate vars in other namespaces.

eg. ; annotate the var foo in this namespace
    (ann foo [Number -> Number])

    ; annotate a var in another namespace
    (ann another.ns/bar [-> nil])
 
    ; don't check this var
    (ann ^:no-check foobar [Integer -> String])

ann-datatype

macro

(ann-datatype & args)
Annotate datatype Class name dname with expected fields.
If unqualified, qualify in the current namespace.
Takes an optional type variable binder before the name.

Fields must be specified in the same order as presented 
in deftype, with exactly the same field names.

Also annotates datatype factories and constructors.

Binder is a vector of specs. Each spec is a vector
with the variable name as the first entry, followed by
keyword arguments:
- :variance (mandatory)
  The declared variance of the type variable. Possible
  values are :covariant, :contravariant and :invariant.
- :< (optional)
  The upper type bound of the type variable. Defaults to
  Any, or the most general type of the same rank as the
  lower bound.
- :> (optional)
  The lower type bound of the type variable. Defaults to
  Nothing, or the least general type of the same rank as the
  upper bound.

eg. ; a datatype in the current namespace
    (ann-datatype MyDatatype [a :- Number,
                              b :- Long])

    ; a datatype in another namespace
    (ann-datatype another.ns.TheirDatatype
                  [str :- String,
                   vec :- (Vec Number)])

    ; a datatype, polymorphic in a
    (ann-datatype [[a :variance :covariant]]
                  MyPolyDatatype
                  [str :- String,
                   vec :- (Vec Number)
                   ply :- (Set a)])

ann-form

macro

(ann-form form ty)
Annotate a form with an expected type.

ann-interface

macro

(ann-interface & args)
Annotate a possibly polymorphic interface (created with definterface) with method types.

Note: Unlike ann-protocol, omit the target ('this') argument in the method signatures.

eg. (ann-interface IFoo
      bar
      (Fn [-> Any]
          [Number Symbol -> Any])
      baz
      [Number -> Number])
    (definterface IFoo
      (bar [] [n s])
      (baz [n]))

    ; polymorphic protocol
    ; x is scoped in the methods
    (ann-protocol [[x :variance :covariant]]
      IFooPoly
      bar
      (Fn [-> Any]
          [Number Symbol -> Any])
      baz
      [Number -> Number])
    (definterface IFooPoly
      (bar [] [n s])
      (baz [n]))

ann-many

macro

(ann-many t & vs)
Annotate several vars with type t.

eg. (ann-many FakeSearch
              web1 web2 image1 image2 video1 video2)

ann-protocol

macro

(ann-protocol & args)
Annotate a possibly polymorphic protocol var with method types.

eg. (ann-protocol IFoo
      bar
      (IFn [IFoo -> Any]
           [IFoo Number Symbol -> Any])
      baz
      [IFoo Number -> Number])
    (t/tc-ignore
      (defprotocol IFoo
        (bar [this] [this n s])
        (baz [this n])))

    ; polymorphic protocol
    ; x is scoped in the methods
    (ann-protocol [[x :variance :covariant]]
      IFooPoly
      bar
      (IFn [(IFooPoly x) -> Any]
           [(IFooPoly x) Number Symbol -> Any])
      baz
      [(IFooPoly x) Number -> Number])
    (t/tc-ignore
      (defprotocol IFooPoly
        (bar [this] [this n s])
        (baz [this n])))

ann-record

macro

(ann-record & args)
Annotate record Class name dname with expected fields.
If unqualified, qualify in the current namespace.
Takes an optional type variable binder before the name.

Fields must be specified in the same order as presented 
in defrecord, with exactly the same field names.

Also annotates record factories and constructors.

Binder is a vector of specs. Each spec is a vector
with the variable name as the first entry, followed by
keyword arguments:
- :variance (mandatory)
  The declared variance of the type variable. Possible
  values are :covariant, :contravariant and :invariant.
- :< (optional)
  The upper type bound of the type variable. Defaults to
  Any, or the most general type of the same rank as the
  lower bound.
- :> (optional)
  The lower type bound of the type variable. Defaults to
  Nothing, or the least general type of the same rank as the
  upper bound.

eg. ; a record in the current namespace
    (ann-record MyRecord [a :- Number,
                          b :- Long])

    ; a record in another namespace
    (ann-record another.ns.TheirRecord
                [str :- String,
                 vec :- (Vec Number)])

    ; a record, polymorphic in a
    (ann-record [[a :variance :covariant]]
                MyPolyRecord
                [str :- String,
                 vec :- (Vec Number)
                 ply :- (Set a)])

atom

macro

(atom & args)
Like atom, but with optional type annotations.

Same as (atom (ann-form init t) args*)

eg. (atom 1) : (Atom (Value 1))
    (atom :- Num, 1) : (Atom Num)

cast

macro

(cast t x)(cast t x opt)
Cast a value to a type. Returns a new value that conforms
to the given type, otherwise throws an error with blame.

eg. (cast Int 1)
    ;=> 1

    (cast Int nil)
    ; Fail, <blame positive ...>

    ((cast [Int -> Int] identity)
     1)
    ;=> 1

    ((cast [Int -> Int] identity)
     nil)
    ; Fail, <blame negative ...>

    (cast [Int -> Int] nil)
    ; Fail, <blame positive ...>

(defalias Options
  (HMap :optional {:positive (U Sym Str),
                   :negative (U Sym Str)
                   :file (U Str nil)
                   :line (U Int nil)
                   :column (U Int nil)}))

(IFn [Contract Any -> Any]
     [Contract Any Options -> Any])

Options:
- :positive   positive blame, (U Sym Str)
- :negative   negative blame, (U Sym Str)
- :file       file name where contract is checked, (U Str nil)
- :line       line number where contract is checked, (U Int nil)
- :column     column number where contract is checked, (U Int nil)

cf

macro

(cf form)(cf form expected)
Takes a form and an optional expected type and
returns a human-readable inferred type for that form.
Throws an exception if type checking fails.

Do not use cf inside a typed namespace. cf is intended to be
used at the REPL or within a unit test. Note that testing for
truthiness is not sufficient to unit test a call to cf, as nil
and false are valid type syntax.

cf preserves annotations from previous calls to check-ns or cf,
and keeps any new ones collected during a cf. This is useful for
debugging and experimentation. cf may be less strict than check-ns
with type checker warnings.

eg. (cf 1) 
    ;=> Long

    (cf #(inc %) [Number -> Number])
    ;=> [Number -> Number]

check-form*

(check-form* form)(check-form* form expected)(check-form* form expected type-provided? & opt)
Function that takes a form and optional expected type syntax and
type checks the form. If expected is provided, type-provided?
must be true.

Takes same options as check-form-info, except 2nd argument is :expected,
3rd argument is :type-provided?, and subsequent keys in opt will be merged over
them.

check-form-info

(check-form-info form & {:as opt})
Function that type checks a form and returns a map of results from type checking the
form.

Options
- :expected        Type syntax representing the expected type for this form
                   type-provided? option must be true to utilise the type.
- :type-provided?  If true, use the expected type to check the form.
- :file-mapping    If true, return map provides entry :file-mapping, a hash-map
                   of (Map '{:line Int :column Int :file Str} Str).
- :checked-ast     Returns the entire AST for the given form as the :checked-ast entry,
                   annotated with the static types inferred after checking.
                   If a fatal error occurs, mapped to nil.
- :beta-limit      A natural integer which denotes the maximum number of beta reductions
                   the type system can perform on a single top-level form (post Gilardi-scenario).
- :check-config    Configuration map for the type checker. (See corresponding option for `check-ns`)

Default return map
- :ret             TCResult inferred for the current form
- :out-form        The macroexpanded result of type-checking, if successful. 
- :result          The evaluated result of :out-form, if any.
- :ex              A fatal exception thrown during checking, if any.
- :type-errors     A non-empty vector of delayed errors.

check-ns

(check-ns)(check-ns ns-or-syms & {:as opt})
Type check a namespace/s (a symbol or Namespace, or collection).
If not provided default to current namespace.
Returns a true value if type checking is successful, otherwise
throws an Exception.

Do not use check-ns within a checked namespace.
It is intended to be used at the REPL or within a unit test.
Suggested idiom for clojure.test: (is (check-ns 'your.ns))

Keyword arguments:
- :trace         If true, print some basic tracing of the type checker
                 Default: nil
- :verbose-types       If true, print fully qualified types. {:unique-tvars true} to print type variables with unique internal names.
                       Default: nil
- :verbose-forms    If true, to print full forms in error messages.
                    Default: nil
- :check-config   Configuration map for the type checker.
  - :check-ns-dep  If `:recheck`, always check dependencies.
                   If `:never`, ns dependencies are ignored.
                   #{:recheck :never}
                   Default: :never
  - :unannotated-def   If `:unchecked`, unannotated `def`s are ignored
                       and their type is not recorded.
                       If `:infer`, unannotated `def`s are inferred by their
                       root binding and the type is recorded in the type environment.
                       #{:unchecked :infer}
                       Also applies to `defmethod`s on unannotated `defmulti`s.
                       Default: :infer
  - :unannotated-var   If `:unchecked`, unannotated vars are given an *unsound*
                       annotation that is used to statically infer its type
                       based on usages/definition (see `infer-unannotated-vars`).
                       If `:any`, usages of unannotated vars are given type `Any` (sound).
                       If `:error`, unannotated vars are a type error (sound).
                       #{:unchecked :any :error}
                       Default: :error
  - :unannotated-arg   (Not Yet Implemented)
                       If `:unchecked`, unannotated fn arguments are given an *unsound*
                       annotation that is used to statically infer its argument types
                       based on definition.
                       If `:any`, unannotated fn arguments are give type `Any` (sound).
                       #{:unchecked :any}
                       Default: :any
  - :check-form-eval   Configures when to evaluate a form relative to type checking it.
                       If :never, don't evaluate individual forms as part of type checking.
                       Avoids side effects during expansion and analysis.
                       If :before, evaluate entire individual forms before type checking, ignoring
                       the Gilardi scenario. Avoids side effects during expansion and analysis.
                       If :after, evaluate individual forms after type checking, respecting the
                       Gilardi scenario.
                       Default: :never
  - :check-ns-load     If :require-before-check, `require` all checked namespaces before checking.
                       If :never, don't load files before checking.
                       Default: :require-before-check


If providing keyword arguments, the namespace to check must be provided
as the first argument.

eg. (check-ns 'myns.typed)
    ;=> :ok
   
    ; implicitly check current namespace
    (check-ns)
    ;=> :ok

check-ns-info

(check-ns-info)(check-ns-info ns-or-syms & opt)
Same as check-ns, but returns a map of results from type checking the
namespace.

Options
- :type-provided?  If true, use the expected type to check the form
- :file-mapping    If true, return map provides entry :file-mapping, a hash-map
of (Map '{:line Int :column Int :file Str} Str).
- :check-deps      If true, recursively type check namespace dependencies.
Default: true

Return map
- :ex           A fatal exception thrown during checking, if any.
- :type-errors  If present, a non-empty vector of delayed errors. See [[doc/errors.md]].

check-ns2

(check-ns2)(check-ns2 ns-or-syms & {:as opt})

declare-alias-kind

macro

(declare-alias-kind sym ty)
Declare a kind for an alias, similar to declare but on the kind level.

declare-datatypes

macro

(declare-datatypes & syms)
Declare datatypes, similar to declare but on the type level.

declare-names

macro

(declare-names & syms)
Declare names, similar to declare but on the type level.

declare-protocols

macro

(declare-protocols & syms)
Declare protocols, similar to declare but on the type level.

def

macro

(def name & fdecl)
Like clojure.core/def with optional type annotations. Registers
annotations like t/ann.

NB: in Clojure it not useful refer a macro called `def` as it is a
special form. Use an alias prefix (eg., `t/def`).

eg. ;same as clojure.core/def
    (def vname 1)
    
    ;with Number `ann`
    (def vname :- Number 1)

    ;doc
    (def vname
      "Docstring"
      :- Long
      1)

defalias

macro

(defalias sym doc-str t)(defalias sym t)
Define a recursive type alias on a qualified symbol. Takes an optional doc-string as a second
argument.

Updates the corresponding var with documentation.

eg. (defalias MyAlias
      "Here is my alias"
      (U nil String))

    ;; recursive alias
    (defalias Expr
      (U '{:op ':if :test Expr :then Expr :else Expr}
         '{:op ':const :val Any}))

default-check-config

(default-check-config)

defn

macro

(defn & args)
Like defn, but registers annotation with t/ann.

eg. (defn fname [a :- Number, b :- (U Symbol nil)] :- Integer ...)

;annotate return
(defn fname [a :- String] :- String ...)

;multi-arity
(defn fname 
  ([a :- String] :- String ...)
  ([a :- String, b :- Number] :- Long ...))

;polymorphic function
(defn :forall [x y]
  fname 
  ([a :- x] :- (Coll y) ...)
  ([a :- Str, b :- y] :- y ...))

defprotocol

macro

(defprotocol & body)
Like defprotocol, but with optional type annotations.

Omitted annotations default to Any. The first argument
of a protocol cannot be annotated.

Add a binder before the protocol name to define a polymorphic
protocol. A binder before the method name defines a polymorphic
method, however a method binder must not shadow type variables
introduced by a protocol binder.

Return types for each method arity can be annotated.

Unlike clojure.core/defprotocol, successive methods can
have the same arity. Semantically, providing multiple successive
methods of the same arity is the same as just providing the left-most
method. However the types for these methods will be accumulated into
a Fn type.

eg. ;annotate single method
(defprotocol MyProtocol
  (a [this a :- Integer] :- Number))

;polymorphic protocol
(defprotocol [[x :variance :covariant]]
  MyProtocol
  (a [this a :- Integer] :- Number))

;multiple types for the same method
(defprotocol [[x :variance :covariant]]
  MyProtocol
  (a [this a :- Integer] :- Integer
     [this a :- Long] :- Long
     [this a :- Number] :- Number))

;polymorphic method+protocol
(defprotocol [[x :variance :covariant]]
  MyProtocol
  ([y] a [this a :- x, b :- y] :- y))

dotimes

macro

(dotimes bindings & body)
Like clojure.core/dotimes, but with optional annotations.

If annotation for binding is omitted, defaults to Int.

eg. (dotimes [_ 100]
      (println "like normal"))

    (dotimes [x :- Num, 100.123]
      (println "like normal" x))

envs

(envs)
Returns a map of type environments, according to the current state of the
type checker.

Output map:
- :vars      map from var symbols to their verbosely printed types
- :aliases   map from alias var symbols (made with defalias) to their verbosely printed types
- :special-types  a set of Vars that are special to the type checker (like Any, U, I)

fn

macro

(fn & forms)
Like clojure.core/fn, but with optional annotations.

eg. ;these forms are equivalent
    (fn [a] b)
    (fn [a :- Any] b)
    (fn [a :- Any] :- Any b)
    (fn [a] :- Any b)

    ;annotate return
    (fn [a :- String] :- String body)

    ;named fn
    (fn fname [a :- String] :- String body)

    ;rest parameter
    (fn [a :- String & b :- Number *] body)

    ;dotted rest parameter
    (fn [a :- String & b :- Number :.. x] body)

    ;multi-arity
    (fn fname 
      ([a :- String] :- String ...)
      ([a :- String, b :- Number] :- String ...))

    ; polymorphic binder
    (fn :forall [x y z]
      fname 
      ([a :- String] :- String ...)
      ([a :- String, b :- Number] :- String ...))

inst

macro

(inst inst-of & types)
Instantiate a polymorphic type with a number of types.

eg., (inst foo-fn t1 t2 t3 ...)

To instantiate dotted variable to T1 T2, use (t/cat T1 T2).

inst-ctor

macro

(inst-ctor inst-of & types)
Instantiate a call to a constructor with a number of types.
First argument must be an immediate call to a constructor.
Returns exactly the instantiatee (the first argument).

eg. (inst-ctor (PolyCtor. a b c)
               t1 t2 ...)

into-array>

macro

(into-array> cljt coll)(into-array> javat cljt coll)(into-array> into-array-syn javat cljt coll)
Make a Java array with Java class javat and Typed Clojure type
cljt. Resulting array will be of type javat, but elements of coll must be under
cljt. cljt should be a subtype of javat (the same or more specific).

*Temporary hack*
into-array-syn is exactly the syntax to put as the first argument to into-array.
Calling resolve on this syntax should give the correct class.

let

macro

(let bvec & forms)
Like clojure.core/let but supports optional type annotations.

eg. (let [a :- Type, b
          a2 1.2]
      body)

letfn>

macro

(letfn> fn-specs-and-annotations & body)
Like letfn, but each function spec must be annotated.

eg. (letfn> [a :- [Number -> Number]
             (a [b] 2)

             c :- [Symbol -> nil]
             (c [s] nil)]
      ...)

load-if-needed

(load-if-needed)
Load and initialize all of core.typed if not already

loop

macro

(loop bindings & exprs)
Like clojure.core/loop, and supports optional type annotations.
Arguments default to a generalised type based on the initial value.

eg. (loop [a :- Number 1
           b :- (U nil Number) nil]
      ...)

method-type

(method-type mname)
Given a method symbol, print the core.typed types assigned to it.
Intended for use at the REPL.

nilable-param

macro

(nilable-param msym mmap)
Override which parameters in qualified method msym may accept
nilable values. If the parameter is a parameterised type or
an Array, this also declares the parameterised types and the Array type as nilable.

mmap is a map mapping arity parameter number to a set of parameter
positions (integers). If the map contains the key :all then this overrides
other entries. The key can also be :all, which declares all parameters nilable.

non-nil-return

macro

(non-nil-return msym arities)
Override the return type of fully qualified method msym to be non-nil.
Takes a set of relevant arities,
represented by the number of parameters it takes (rest parameter counts as one),
or :all which overrides all arities.

eg. ; must use full class name
    (non-nil-return java.lang.Class/getDeclaredMethod :all)

override-constructor

macro

(override-constructor ctorsym typesyn)
Override all constructors for Class ctorsym with type.

override-method

macro

(override-method methodsym typesyn)
Override type for qualified method methodsym.

methodsym identifies the method to override and should be a
namespace-qualified symbol in the form <class>/<method-name>.
The class name needs to be fully qualified.

typesyn uses the same annotation syntax as functions.

Use non-nil-return instead of override-method if you want to
declare that a method can never return nil.

Example:

  (override-method java.util.Properties/stringPropertyNames
                   [-> (java.util.Set String)])

This overrides the return type of method stringPropertyNames
of class java.util.Properties to be (java.util.Set String).

pred

macro

(pred t)
Generate a flat (runtime) predicate for type that returns true if the
argument is a subtype of the type, otherwise false.

The current type variable and dotted type variable scope is cleared before parsing.

eg. ((pred Number) 1)
    ;=> true

print-env

(print-env debug-str)
During type checking, print the type environment to *out*,
preceeded by literal string debug-str.

print-filterset

(print-filterset debug-string frm)
During type checking, print the filter set attached to form, 
preceeded by literal string debug-string.
Returns nil.

eg. (let [s (seq (get-a-seqable))]
      (print-filterset "Here now" s))

ref

macro

(ref & args)
Like ref, but with optional type annotations.

Same as (ref (ann-form init t) args*)

eg. (ref 1) : (Ref (Value 1))
    (ref :- Num, 1) : (Ref Num)

register!

(register!)
Internal -- Do not use

reset-caches

(reset-caches)
Reset internal type caches.

statistics

(statistics nsyms)
Takes a collection of namespace symbols and returns a map mapping the namespace
symbols to a map of data

tc-ignore

macro

(tc-ignore & body)
Ignore forms in body during type checking

untyped-var

macro

(untyped-var varsym typesyn)
Check a given var has the specified type at runtime.

var-coverage

(var-coverage)(var-coverage nsyms-or-nsym)
Summarises annotated var coverage statistics to *out*
for namespaces nsyms, a collection of symbols or a symbol/namespace.
Defaults to the current namespace if no argument provided.

warn-on-unannotated-vars

macro

(warn-on-unannotated-vars)
Allow unannotated vars in the current namespace. 

Emits a warning instead of a type error when checking
a def without a corresponding expected type.

Disables automatic inference of `def` expressions.

eg. (warn-on-unannotated-vars)

when-let-fail

macro

(when-let-fail b & body)
Like when-let, but fails if the binding yields a false value.