├── src ├── test │ ├── clojure │ │ └── clojure │ │ │ └── core │ │ │ └── typed │ │ │ └── test │ │ │ ├── reader.clj │ │ │ ├── ann_qualify │ │ │ ├── parent.clj │ │ │ └── child.clj │ │ │ ├── macro.clj │ │ │ ├── gradual │ │ │ ├── untyped.clj │ │ │ └── import_untyped.clj │ │ │ ├── ctyp_294 │ │ │ ├── untyped.clj │ │ │ └── typed.clj │ │ │ ├── mapping_test_file.clj │ │ │ ├── line_number.clj │ │ │ ├── protocol_in_another_ns.clj │ │ │ ├── hello_world.clj │ │ │ ├── for.clj │ │ │ ├── pred_scoping.clj │ │ │ ├── analyze_test.clj │ │ │ ├── def_arrow.clj │ │ │ ├── duplicate_ann.clj │ │ │ ├── binding.clj │ │ │ ├── parse_ast.clj │ │ │ ├── finally.clj │ │ │ ├── fail │ │ │ ├── plain_defprotocol.clj │ │ │ ├── record_no_nil.clj │ │ │ ├── unannotated_record.clj │ │ │ ├── recur_empty_seq.clj │ │ │ ├── recur_non_seq_rest.clj │ │ │ ├── record_as_datatype.clj │ │ │ ├── datatype_as_record.clj │ │ │ ├── CTYP_45.clj │ │ │ ├── record_poly_no_optional.clj │ │ │ └── reflection.clj │ │ │ ├── pred_static.clj │ │ │ ├── promise.clj │ │ │ ├── recur_rest_arg.clj │ │ │ ├── hmap_resolve_assoc.clj │ │ │ ├── mm_warn_on_unannotated.clj │ │ │ ├── CTYP_124_case_update_default.clj │ │ │ ├── CTYP_234 │ │ │ ├── dep.clj │ │ │ └── core.clj │ │ │ ├── var_usage.clj │ │ │ ├── ctyp_263.clj │ │ │ ├── CTYP_101_mapentry.clj │ │ │ ├── nocheck.clj │ │ │ ├── set_bang.clj │ │ │ ├── variance_test.clj │ │ │ ├── runtime_check.clj │ │ │ ├── dyn_propagate.clj │ │ │ ├── unannotated_datatype.clj │ │ │ ├── record_optional_key.clj │ │ │ ├── hvec_dotted.clj │ │ │ ├── datatype_recur.clj │ │ │ ├── protocol_fail.clj │ │ │ ├── warn_on_unannotated_var.clj │ │ │ ├── nested_tfn_operator.clj │ │ │ ├── some_fn.clj │ │ │ ├── interop.clj │ │ │ ├── project.clj │ │ │ ├── heterogeneous_restarg.clj │ │ │ ├── collatz.clj │ │ │ ├── kw_args_undeclared_fail.clj │ │ │ ├── unsound_record.clj │ │ │ ├── shell.clj │ │ │ ├── swap_bang.clj │ │ │ ├── filter_simplify.clj │ │ │ ├── record_poly_map_ctor.clj │ │ │ ├── succeed │ │ │ ├── CTYP_42_record_extend_protocol.clj │ │ │ └── CTYP49_unreachable.clj │ │ │ ├── non_literal_val_fn.clj │ │ │ ├── trampoline.clj │ │ │ ├── protocol_munge.clj │ │ │ ├── load_test.clj │ │ │ ├── data.clj │ │ │ ├── check_tc.clj │ │ │ ├── edn.clj │ │ │ ├── last_test.clj │ │ │ ├── poly.clj │ │ │ ├── trans_dots.clj │ │ │ ├── mapv_test.clj │ │ │ ├── reflect.clj │ │ │ ├── browse.clj │ │ │ ├── person.clj │ │ │ ├── ctyp_284.clj │ │ │ ├── ctyp_257.clj │ │ │ ├── filter_combine.clj │ │ │ ├── bug1.clj │ │ │ ├── get_bounded_tvar.clj │ │ │ ├── protocol_scoping.clj │ │ │ ├── CTYP_37.clj │ │ │ ├── forward_variance.clj │ │ │ ├── error_msg.clj │ │ │ ├── io.clj │ │ │ ├── CTYP_118_cast.clj │ │ │ ├── filter_unit_tests.clj │ │ │ ├── pred_hmap.clj │ │ │ ├── cljc.clj │ │ │ ├── file_mapping.clj │ │ │ ├── util_aliases.clj │ │ │ ├── CTYP146.clj │ │ │ ├── contract_utils_test.clj │ │ │ ├── hsequential.clj │ │ │ ├── symbolic_closures.clj │ │ │ ├── munge_record_field.clj │ │ │ ├── ctyp_258.clj │ │ │ ├── ctyp_255.clj │ │ │ ├── slow.clj │ │ │ ├── tools_analyzer.clj │ │ │ ├── recursive.clj │ │ │ ├── cast.clj │ │ │ ├── template.clj │ │ │ ├── rec_protocol.clj │ │ │ ├── CTYP_83_performance.clj │ │ │ ├── defprotocol.clj │ │ │ ├── tap.clj │ │ │ ├── records.clj │ │ │ ├── CTYP_144.clj │ │ │ ├── assoc.clj │ │ │ ├── set_test.clj │ │ │ ├── atom.clj │ │ │ ├── ring.clj │ │ │ ├── poly_record.clj │ │ │ ├── pomegranate.clj │ │ │ ├── protocol_untyped_extend.clj │ │ │ ├── protocol.clj │ │ │ ├── csgen_intersection.clj │ │ │ ├── array_old.clj │ │ │ ├── unsound_simplify.clj │ │ │ ├── repl_new.clj │ │ │ ├── tag_test.clj │ │ │ ├── ctyp97_tvar_scoping.clj │ │ │ ├── string.clj │ │ │ ├── stacktrace.clj │ │ │ ├── edn_parser.clj │ │ │ ├── javadoc.clj │ │ │ ├── jvm │ │ │ └── array.clj │ │ │ ├── ctyp105.clj │ │ │ ├── instant.clj │ │ │ ├── mm.clj │ │ │ ├── kw_args.clj │ │ │ ├── cps.clj │ │ │ ├── extend_record.clj │ │ │ ├── pprint.clj │ │ │ ├── inspector.clj │ │ │ ├── letfn_runtime.clj │ │ │ ├── destructure.clj │ │ │ ├── namespaced_specials.clj │ │ │ ├── rbt_types.clj │ │ │ ├── async.clj │ │ │ └── core_match.clj │ └── resources │ │ └── clojure │ │ └── core │ │ └── typed │ │ └── test │ │ ├── load_file.clj │ │ ├── dummy_cljc.cljc │ │ ├── duplicated.clj │ │ ├── reader_cond.cljc │ │ ├── ns_reader_cond.cljc │ │ ├── load_file2.clj │ │ ├── typed_load │ │ ├── eval.clj │ │ ├── bad_dep.clj │ │ └── uses_bad_dep.clj │ │ └── duplicated.cljc ├── assembly │ └── slim.xml └── main │ └── clojure │ └── clojure │ └── core │ └── typed │ ├── checker │ ├── hset_utils.clj │ ├── errors_ann.clj │ ├── indirect_ann.clj │ ├── coerce_ann.clj │ ├── check │ │ ├── local.clj │ │ ├── binding.clj │ │ ├── quote.clj │ │ ├── multi_utils.clj │ │ ├── invoke.clj │ │ ├── set_bang.clj │ │ ├── multi.clj │ │ ├── monitor.clj │ │ ├── vector.clj │ │ ├── throw.clj │ │ ├── catch.clj │ │ ├── seq_ops.clj │ │ ├── special │ │ │ └── tc_ignore.clj │ │ ├── recur_utils.clj │ │ ├── fn.clj │ │ ├── with_meta.clj │ │ ├── get.clj │ │ ├── set.clj │ │ ├── const.clj │ │ ├── print_env.clj │ │ ├── case.clj │ │ └── try.clj │ ├── def_utils.clj │ ├── jvm │ │ ├── reset_caches.clj │ │ ├── reflect_utils.clj │ │ ├── rclass_env.clj │ │ ├── method_override_env.clj │ │ ├── method_return_nilables.clj │ │ ├── ctor_override_env.clj │ │ ├── method_param_nilables.clj │ │ ├── check_ns_clj.clj │ │ └── array_ops.clj │ ├── indirect_ops.clj │ ├── nilsafe_utils.clj │ ├── dvar_env.clj │ ├── ns_options.clj │ ├── indirect_utils.clj │ ├── collect_utils.clj │ ├── remove.clj │ ├── local_result.clj │ ├── declared_kind_env.clj │ ├── reset_env.clj │ ├── fold_rep.clj │ ├── init.clj │ ├── impl_protocols.clj │ └── datatype_env.clj │ ├── contract_ann.clj │ └── contrib_annotations.clj ├── script ├── repl ├── test ├── move-ns.sh ├── current-version.sh ├── current-coord.sh └── sync-master.sh ├── images └── part-of-typed-clojure-project.png ├── .gitignore ├── .circleci └── config.yml ├── .github └── workflows │ └── clj.yml ├── README.md └── deps.edn /src/test/clojure/clojure/core/typed/test/reader.clj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /script/repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | clj -Atest:nREPL "$@" 4 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | clojure -Atest:runner "$@" 4 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/load_file.clj: -------------------------------------------------------------------------------- 1 | (ns ^:core.typed clojure.core.typed.test.load-file) 2 | 3 | (inc 'a) 4 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ann_qualify/parent.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ann-qualify.parent) 2 | 3 | (def a 1) 4 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/macro.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.macro) 2 | 3 | (defmacro anything [& a] 4 | `(if 1 ~a 1)) 5 | -------------------------------------------------------------------------------- /images/part-of-typed-clojure-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clojure/core.typed.checker.jvm/master/images/part-of-typed-clojure-project.png -------------------------------------------------------------------------------- /script/move-ns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | git grep -l clojure\.core\.typed\.$1 | xargs sed -i '' "s/clojure\.core\.typed\.$1/clojure.core.typed.$2/g" 4 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/gradual/untyped.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.gradual.untyped) 2 | 3 | (def a 1) 4 | (def b nil) 5 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/dummy_cljc.cljc: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.dummy-cljc 2 | (:require [clojure.core.typed :as t])) 3 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/duplicated.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.duplicated 2 | (:require [clojure.core.typed :as t])) 3 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_294/untyped.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-294.untyped) 2 | 3 | (def foo inc) 4 | (def bar 1) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/mapping_test_file.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.mapping-test-file) 2 | 3 | (let [a (+ 1 2)] 4 | a) 5 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/reader_cond.cljc: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.reader-cond 2 | (:require [#?(:clj clojure.core.typed) :as t])) 3 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/line_number.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.line-number 2 | (:require [clojure.core.typed :as t])) 3 | 4 | #(identity nil nil) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol_in_another_ns.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol-in-another-ns) 2 | 3 | (defprotocol AnotherNs 4 | (baz [this])) 5 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/ns_reader_cond.cljc: -------------------------------------------------------------------------------- 1 | #?(:clj 2 | (ns clojure.core.typed.test.ns-reader-cond 3 | {:lang :core.typed})) 4 | 5 | #(inc 'a) 6 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/load_file2.clj: -------------------------------------------------------------------------------- 1 | (ns ^:core.typed clojure.core.typed.test.load-file2 2 | (:require [clojure.core.typed.test.load-file])) 3 | 4 | (inc 'b) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/hello_world.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.hello-world 2 | (:require [clojure.core.typed :refer [check-ns]])) 3 | 4 | (pr-str "Hello world") 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/for.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.for 2 | (:require [clojure.core.typed :as t :refer [IFn]])) 3 | 4 | (t/for [x :- t/Num, [1 2 3 4]] :- t/Num x) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/pred_scoping.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.pred-scoping 2 | (:require [clojure.core.typed :as unique123 :refer [pred]])) 3 | 4 | (pred unique123/Int) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/analyze_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.analyze-test 2 | (:require [clojure.core.typed.checker.jvm.analyze-clj :as ana])) 3 | 4 | (let [{:keys [a]} nil]) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/def_arrow.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.def-arrow 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/def a :- Number, 1) 5 | 6 | (assert (= (+ a 1) 2)) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/duplicate_ann.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.duplicate-ann 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann foo Number) 5 | 6 | (t/ann foo Integer) 7 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/typed_load/eval.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.typed-load.eval 2 | {:lang :core.typed} 3 | (:require [clojure.core.typed :as t])) 4 | 5 | (t/cast t/Int nil) 6 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/binding.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.binding 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/def ^:dynamic *foo* :- Boolean, true) 5 | (binding [*foo* false]) 6 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/parse_ast.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.parse-ast 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann-record Top []) 5 | (defrecord Top []) 6 | 7 | (t/defalias A Top) 8 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/duplicated.cljc: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.duplicated 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; this is intentional type error for test purposes 5 | (inc 'a) 6 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/typed_load/bad_dep.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.typed-load.bad-dep 2 | {:lang :core.typed}) 3 | 4 | ;; this will only throw a type error on the first load 5 | (inc 'a) 6 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/finally.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.finally 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann f [-> String]) 5 | (defn f [] 6 | (try 7 | "a" 8 | (finally 1))) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/plain_defprotocol.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.plain-defprotocol 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; should throw top level type error 5 | (defprotocol Foo (bar [this])) 6 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/record_no_nil.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.record-no-nil 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann-record Foo [a :- Number]) 5 | (defrecord Foo [a]) 6 | 7 | (map->Foo {}) 8 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/unannotated_record.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.unannotated-record 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ;Should throw a top level type error 5 | (defrecord Unannotated []) 6 | -------------------------------------------------------------------------------- /script/current-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | MVN_VERSION=$(mvn -o -q \ 6 | -Dexec.executable=echo \ 7 | -Dexec.args='${project.version}' \ 8 | --non-recursive \ 9 | exec:exec) 10 | 11 | echo $MVN_VERSION 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/pred_static.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.pred-static 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (let [a (t/ann-form {:a 1} Any) 5 | _ (assert ((t/pred '{:a Number}) a))] 6 | (+ 1 (:a a))) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/promise.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.promise 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann p (t/Promise Number)) 5 | (def p (promise)) 6 | 7 | (fn [] 8 | (p 1) 9 | 10 | (inc @p)) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/recur_rest_arg.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.recur-rest-arg 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann recur-args [Number * -> t/Any]) 5 | (defn recur-args 6 | [& args] 7 | (recur args)) 8 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ann_qualify/child.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ann-qualify.child 2 | (:require [clojure.core.typed :as t] 3 | [clojure.core.typed.test.ann-qualify.parent :as p])) 4 | 5 | (t/ann p/a t/Int) 6 | (inc p/a) 7 | -------------------------------------------------------------------------------- /script/current-coord.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | MVN_VERSION=$(mvn -o -q \ 6 | -Dexec.executable=echo \ 7 | -Dexec.args='${project.groupId}/${project.artifactId}' \ 8 | --non-recursive \ 9 | exec:exec) 10 | 11 | echo $MVN_VERSION 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/recur_empty_seq.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.recur-empty-seq 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann recur-args-fail [Number * -> t/Any]) 5 | (defn recur-args-fail [& args] 6 | (recur ())) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/recur_non_seq_rest.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.recur-non-seq-rest 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann recur-args-fail [Number * -> t/Any]) 5 | (defn recur-args-fail [& args] 6 | (recur [1 2 3])) 7 | -------------------------------------------------------------------------------- /src/test/resources/clojure/core/typed/test/typed_load/uses_bad_dep.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.typed-load.uses-bad-dep 2 | {:lang :core.typed} 3 | ;; this only type checks once, then caches like `require` 4 | (:require [clojure.core.typed.test.typed-load.bad-dep])) 5 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/record_as_datatype.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.record-as-datatype 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ;Should throw a top level type error 5 | (t/ann-datatype IncorrectRec []) 6 | (defrecord IncorrectRec []) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/hmap_resolve_assoc.clj: -------------------------------------------------------------------------------- 1 | ;CTYP-79 2 | (ns clojure.core.typed.test.hmap-resolve-assoc 3 | (:require [clojure.core.typed :as t])) 4 | 5 | (t/defalias TA (t/HMap :optional {:d t/Any})) 6 | 7 | (t/ann a [TA -> TA]) 8 | (defn a [m] (assoc m :d "foo")) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/mm_warn_on_unannotated.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.mm-warn-on-unannotated 2 | (:require [clojure.core.typed :as t :refer [check-ns]])) 3 | 4 | (t/warn-on-unannotated-vars) 5 | 6 | (defmulti foo class) 7 | 8 | (defmethod foo Object [a] 1) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/datatype_as_record.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.datatype-as-record 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ;Should throw a top level type error 5 | (clojure.core.typed/ann-record IncorrectDt []) 6 | (deftype IncorrectDt []) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_124_case_update_default.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-124-case-update-default 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann case-default [(t/U ':a ':b) -> ':b]) 5 | (defn case-default [e] 6 | (case e 7 | :a :b 8 | e)) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_234/dep.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-234.dep 2 | {:core.typed {:collect-only true}} 3 | (:require [clojure.core.typed :as t])) 4 | 5 | (t/defalias MyType 6 | (t/HMap :mandatory {:foo String 7 | :bar t/AnyInteger})) 8 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/var_usage.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.var-usage 2 | (:require [clojure.core.typed :refer [ann check-ns]])) 3 | 4 | (ann foo [Number -> Number]) 5 | (declare foo) 6 | 7 | (ann bar [Number -> Number]) 8 | (defn bar [b] 9 | (+ 2 (foo b))) 10 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_234/core.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-234.core 2 | (:require [clojure.core.typed :as t] 3 | [clojure.core.typed.test.CTYP-234.dep :as other])) 4 | 5 | (t/ann foo [other/MyType -> t/AnyInteger]) 6 | (defn foo 7 | [x] 8 | (:bar x)) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_263.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-263 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed.test.test-utils :refer :all])) 4 | 5 | (deftest catch-type-hint-test 6 | (is-tc-e (try :anything (catch Exception e (.getCause e))))) 7 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_101_mapentry.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-101-mapentry 2 | (:require [clojure.core.typed :as t :refer [ann]])) 3 | 4 | (ann f [(clojure.lang.IPersistentMap t/Keyword t/Int) -> (t/Option (clojure.lang.IMapEntry t/Keyword t/Int))]) 5 | (defn f [m] (first m)) 6 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/nocheck.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.nocheck 2 | (:require [clojure.core.typed :refer [ann check-ns]])) 3 | 4 | (ann ^:no-check foo [Number -> Number]) 5 | (defn foo [a] 6 | 'a) 7 | 8 | (ann bar [Number -> Number]) 9 | (defn bar [b] 10 | (+ 2 (foo b))) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/set_bang.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.set-bang 2 | (:import (clojure.lang Keyword)) 3 | (:require [clojure.core.typed :as t])) 4 | 5 | (t/ann foo Keyword) 6 | (def ^:dynamic foo :foo) 7 | 8 | (t/ann bar [-> Keyword]) 9 | (defn bar [] 10 | (set! foo :bar)) 11 | 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/variance_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.variance-test 2 | (:require [clojure.core.typed :as t])) 3 | 4 | 5 | (t/ann-datatype [[w :variance :contravariant] 6 | [r :variance :covariant]] 7 | FooT 8 | []) 9 | 10 | (deftype FooT []) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/runtime_check.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.runtime-check 2 | {:lang :core.typed 3 | :core.typed {:features #{:runtime-check}}} 4 | (:require [clojure.core.typed :as t])) 5 | 6 | 7 | (t/ann a t/Int) 8 | (def a 1) 9 | 10 | ;(t/ann b t/Int) 11 | ;(def b nil) 12 | 13 | #(inc nil) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/dyn_propagate.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.dyn-propagate 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/tc-ignore 5 | (def a {:a 1})) 6 | 7 | (defn b [local] 8 | (let [i a 9 | l (:a a) 10 | id (identity a) 11 | ] 12 | (t/print-env "there") 13 | (inc l))) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/unannotated_datatype.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.unannotated-datatype 2 | (:require [clojure.core.typed :refer [ann tc-ignore check-ns]])) 3 | 4 | (tc-ignore (deftype NoAnnotate [a])) 5 | 6 | (ann test-fn [-> NoAnnotate]) 7 | (defn test-fn [] 8 | (NoAnnotate. 1)) 9 | 10 | (.a (NoAnnotate. 1)) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/CTYP_45.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.CTYP-45 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; using defprotocol shouldn't throw an internal error 5 | 6 | (t/ann-protocol MyProto 7 | foo 8 | [MyProto -> nil]) 9 | (defprotocol MyProto 10 | (foo [my-proto])) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/record_optional_key.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.record-optional-key 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann-record Foo [a :- (t/U nil Number)]) 5 | (defrecord Foo [a]) 6 | 7 | (map->Foo {}) 8 | 9 | (t/ann-record FooP [a :- (t/U nil Number)]) 10 | (defrecord FooP [a]) 11 | 12 | (map->FooP {}) 13 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/hvec_dotted.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.hvec-dotted 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (declare vector*) 5 | 6 | (t/ann ^:no-check vector* (t/All [x ...] 7 | [x ... x -> '[x ... x]])) 8 | 9 | (t/ann foo [-> '[Number Number Number]]) 10 | (defn foo [] 11 | (vector* 1 2 3)) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/datatype_recur.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.datatype-recur 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defprotocol PBar 5 | (rec [this bar :- t/Num] :- t/Num)) 6 | 7 | (t/ann-datatype Foo []) 8 | (deftype Foo [] 9 | PBar 10 | (rec [this bar] 11 | (if (even? (rand-int 10)) 12 | (recur bar) 13 | bar))) 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *jar 3 | /lib/ 4 | /classes/ 5 | .lein* 6 | *.swp 7 | *.swo 8 | *.aux 9 | *.dvi 10 | *.pdf 11 | *.log 12 | *~ 13 | /.classpath 14 | /.project 15 | /.settings 16 | /bin 17 | .nrepl-port 18 | .repl 19 | .\#* 20 | .idea 21 | **.class 22 | *.iml 23 | .nrepl-port 24 | .DS_Store 25 | .cljs_* 26 | nashorn_* 27 | .cpcache 28 | .rebel_readline_history 29 | junit-output.xml 30 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol_fail.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol-fail 2 | (:require [clojure.core.typed :refer [ann-datatype] :as t])) 3 | 4 | (t/defprotocol AddProtoc 5 | (adder [this amount :- t/Num] :- t/Num)) 6 | 7 | (ann-datatype Accumulator [t :- Number]) 8 | (deftype Accumulator [t] 9 | AddProtoc 10 | (adder [_ i] (Accumulator. (+ t i)))) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/warn_on_unannotated_var.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.warn-on-unannotated-var 2 | (:require [clojure.core.typed :as t :refer [ann check-ns ann-form print-env cf]]) 3 | (:import (clojure.lang IPersistentMap IPersistentVector))) 4 | 5 | (t/warn-on-unannotated-vars) 6 | 7 | (defn foo [a] 8 | (fn [s] (+ s 1))) 9 | 10 | (def bar (+ 1 1.2)) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/record_poly_no_optional.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.record-poly-no-optional 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; all map->* keys are mandatory in polymorphic records 5 | 6 | (t/ann-record [[foo :variance :invariant]] Foo [b :- (U nil Number)]) 7 | (t/tc-ignore 8 | (defrecord Foo [b]) 9 | ) 10 | 11 | (map->Foo {}) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/nested_tfn_operator.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.nested-tfn-operator 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defalias Indirect0 5 | (t/TFn [[x :variance :covariant]] 6 | x)) 7 | 8 | (t/defalias Indirect1 9 | Indirect0) 10 | 11 | (t/ann foo [(Indirect1 Number) -> Number]) 12 | (defn foo [x] 13 | x) 14 | 15 | (foo 1) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/some_fn.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.some-fn 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (let [s (t/ann-form (some-fn number? symbol?) (predicate (U Number t/Symbol)))] 5 | (t/print-env "f")) 6 | 7 | (let [s (t/ann-form (every-pred symbol? number?) (predicate (I Number t/AnyInteger)))] 8 | (t/print-env "f")) 9 | 10 | (comp :b :a) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/interop.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.interop 2 | (:import (java.io File)) 3 | (:require [clojure.core.typed :as t])) 4 | 5 | (t/ann f File) 6 | (def f (File. "a")) 7 | 8 | (t/ann prt (t/U nil String)) 9 | (def prt (.getParent ^File f)) 10 | 11 | (t/non-nil-return java.io.File/getName :all) 12 | (t/ann nme String) 13 | (def nme (.getName ^File f)) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/project.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.project 2 | (:require [clojure.core.typed :refer [ann check-ns] :as t])) 3 | 4 | (ann my-atom (t/Atom1 (t/HMap :mandatory {:a t/Num}))) 5 | (def my-atom (atom {:a 1})) 6 | 7 | (ann my-fn (t/All [x a ...] [t/Any x a ... a -> t/Any])) 8 | (defn my-fn [a b & c] 9 | {:a 2}) 10 | 11 | (swap! my-atom my-fn :a 2) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/heterogeneous_restarg.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.heterogeneous-restarg 2 | (:require [clojure.core.typed :refer [ann check-ns ann-form] 3 | :as t])) 4 | 5 | (ann het-args (t/IFn 6 | [Number -> Number] 7 | [Number Number -> Number])) 8 | (defn het-args [a & [b]] 9 | (cond b (+ a b) 10 | :else a)) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/collatz.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.collatz 2 | (:require [clojure.core.typed :refer [ann] :as t])) 3 | 4 | (ann collatz [Number -> Number]) 5 | (defn collatz [n] 6 | (cond 7 | (= 1 n) 8 | 1 9 | (and (integer? n) 10 | (even? n)) 11 | (collatz (/ n 2)) 12 | :else 13 | (collatz (inc (* 3 n))))) 14 | 15 | (collatz 10) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/kw_args_undeclared_fail.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.kw-args-undeclared-fail 2 | (:require [clojure.core.typed :as t :refer [ann check-ns ann-form cf]])) 3 | 4 | ;; invoking a kw-fn with undeclared keywords is an error 5 | (ann undeclared-kw-invoke-test [& :optional {:foo t/Any} -> nil]) 6 | (defn undeclared-kw-invoke-test [& a]) 7 | 8 | (undeclared-kw-invoke-test :blah 'a) 9 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/unsound_record.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.unsound-record 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann-record Foo [a :- Number]) 5 | (defrecord Foo [a]) 6 | 7 | (t/ann unsound [(t/Map t/Any t/Any) -> Number]) 8 | (defn unsound [r] 9 | (let [r (assoc r :a nil)] 10 | (assert (instance? Foo r)) 11 | (inc (:a r)))) 12 | 13 | (fn [] 14 | (unsound (->Foo 1))) 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/shell.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.shell 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest sh-test 8 | (is-tc-e #(sh) [-> (Map Any Any)] 9 | :requires [[clojure.java.shell :refer [sh]]])) 10 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/swap_bang.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.swap-bang 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann foo (t/Atom1 (t/Map ':a Number))) 5 | (def foo (atom {:a 1})) 6 | 7 | (fn [] 8 | (swap! foo (t/inst assoc (t/Map ':a Number) ':a Number) :a 3)) 9 | 10 | ; 11 | ;(swap! foo (fn [a] a)) 12 | ;(swap! foo (fn [a] a)) 13 | ;(swap! foo (fn [a b] a) 2) 14 | ;(swap! foo (fn [a b] a) 2) 15 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | working_directory: ~/core.typed.checker.jvm 6 | docker: 7 | - image: circleci/openjdk:8-jdk 8 | steps: 9 | - checkout 10 | - run: 11 | command: | 12 | curl -O https://download.clojure.org/install/linux-install.sh 13 | chmod +x linux-install.sh 14 | sudo ./linux-install.sh 15 | - run: ./script/test 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/filter_simplify.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.filter-simplify 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/fn [a :- (t/Nilable (t/NonEmptyVec Number)) 5 | b :- (t/Nilable (t/NonEmptyVec Number))] 6 | (let [a (seq a) 7 | b (seq b) 8 | fa (first a) 9 | fb (first b)] 10 | (t/print-env "before") 11 | (t/print-filterset 12 | "and" 13 | (and a b)))) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/record_poly_map_ctor.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.record-poly-map-ctor 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; can omit fields with ground types 5 | 6 | (t/ann-record [[foo :variance :invariant]] Foo [b :- (t/U nil Number) 7 | c :- foo]) 8 | ; FIXME need defrecord> 9 | (t/tc-ignore 10 | (defrecord Foo [b c]) 11 | ) 12 | 13 | (map->Foo {:c 1 :b 2}) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/succeed/CTYP_42_record_extend_protocol.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.succeed.CTYP-42-record-extend-protocol 2 | (:require [clojure.core.typed :as t] 3 | [clojure.repl :as repl])) 4 | 5 | (t/defprotocol PMaths 6 | (mult-by-two [this] :- PMaths)) 7 | 8 | (t/ann-record SpecialNumber [x :- Number]) 9 | (defrecord SpecialNumber [x] 10 | PMaths 11 | (mult-by-two [this] (assoc this :x (* (:x this) 2)))) 12 | -------------------------------------------------------------------------------- /.github/workflows/clj.yml: -------------------------------------------------------------------------------- 1 | name: Run tests with clj 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Set up JDK 1.11 11 | uses: actions/setup-java@v1 12 | with: 13 | java-version: 1.11 14 | - uses: DeLaGuardo/setup-clojure@2.0 15 | with: 16 | tools-deps: latest 17 | - name: Run tests 18 | run: ./script/test 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/non_literal_val_fn.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.non-literal-val-fn 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann kw-invoke [t/Kw -> (t/U nil t/Num)]) 5 | (defn kw-invoke [k] 6 | (k {:a 1 :b 2})) 7 | 8 | (t/ann sym-invoke [t/Sym -> (t/U nil t/Num)]) 9 | (defn sym-invoke [k] 10 | (k {:a 1 :b 2})) 11 | 12 | (t/ann either-invoke [(t/U t/Kw t/Sym) -> (t/U nil t/Num)]) 13 | (defn either-invoke [k] 14 | (k {:a 1 :b 2})) 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/trampoline.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.trampoline 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (declare funb) 5 | 6 | (t/ann-many [Number -> (t/Rec [f] 7 | (t/U Number [-> (t/U t/Num f)]))] 8 | funa funb) 9 | (defn funa [n] 10 | (if (= n 0) 11 | 0 12 | #(funb (dec n)))) 13 | 14 | (defn funb [n] 15 | (if (= n 0) 16 | 0 17 | #(funa (dec n)))) 18 | 19 | (trampoline funa 100) 20 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol_munge.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol-munge 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defprotocol Foo 5 | (my_dash [this] :- t/Num)) 6 | 7 | (t/ann-protocol Bar 8 | my_dash_interface [Bar -> t/Symbol]) 9 | (definterface Bar 10 | (my_dash_interface [])) 11 | 12 | (t/ann-datatype FooT []) 13 | (deftype FooT [] 14 | Foo 15 | (my_dash [this] 1) 16 | Bar 17 | (my_dash_interface [this] 'a)) 18 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/load_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.load-test 2 | (:require [clojure.core.typed.load :as load] 3 | [clojure.test :refer :all])) 4 | 5 | ;; ensures evaluation occurs 6 | (deftest evaluation-test 7 | (is (try (load/typed-load1 "clojure/core/typed/test/typed_load/eval") 8 | nil 9 | (catch clojure.lang.ExceptionInfo e 10 | (-> e ex-data :blame :file #{"clojure/core/typed/test/typed_load/eval.clj"}))))) 11 | -------------------------------------------------------------------------------- /script/sync-master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | branch_name="$(git symbolic-ref HEAD 2>/dev/null)" || 4 | branch_name="(unnamed branch)" # detached HEAD 5 | 6 | branch_name=${branch_name##refs/heads/} 7 | 8 | MASTER="master" 9 | 10 | set -e 11 | 12 | if [ $branch_name != "$MASTER" ]; then 13 | echo "Must be on $MASTER" 14 | exit 1; 15 | fi 16 | 17 | git pull clojure --ff-only master --tags 18 | git pull typedclojure --ff-only master 19 | git push typedclojure master --tags 20 | git push clojure master --tags 21 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/data.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.data 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest diff-test 7 | (is-tc-e (diff '[1 2 3] '[1 2]) '[Any Any Any] 8 | :requires [[clojure.data :refer [diff]]]) 9 | (is-tc-err (diff '[1 2 3] '[1 2]) (t/List t/Any ) 10 | :requires [[clojure.data :refer [diff]]])) 11 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/fail/reflection.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.fail.reflection 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/fn [a :- java.io.File] 5 | (.setReadOnly a 1)) 6 | 7 | (t/fn [a :- java.io.File] 8 | (.getName a)) 9 | 10 | (fn [a] 11 | (java.io.File. a)) 12 | 13 | (t/ann write-lines [java.io.Writer (t/Option (t/Coll String)) -> nil]) 14 | (defn write-lines [writer lines] 15 | (t/doseq [l :- String lines] 16 | (.write writer "testing") 17 | (println l))) 18 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/check_tc.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.check-tc 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed :refer [check-ns]])) 4 | 5 | #_(deftest check-tc 6 | ;fails in hudson 7 | (is (check-ns '[clojure.core.typed.checker.utils 8 | clojure.core.typed.checker.type-rep 9 | clojure.core.typed.checker.cs-rep 10 | clojure.core.typed.checker.name-env 11 | clojure.core.typed.checker.type-ctors]))) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/edn.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.edn 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest read-string-test 8 | (is-tc-e #(edn/read-string "abc") 9 | :requires [[clojure.edn :as edn]]) 10 | (is-tc-err #(edn/read-string "abc") [-> String] 11 | :requires [[clojure.edn :as edn]])) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/last_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.last-test 2 | (:refer-clojure :exclude [fn]) 3 | (:require [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.test :refer :all] 5 | [clojure.core.typed :as t :refer [ann-form print-env fn]])) 6 | 7 | (deftest last-test 8 | (testing "when we know there is at least one value" 9 | (is-tc-e 10 | (fn [coll :- (NonEmptySeqable Long)] 11 | (let [value (last coll)] 12 | (ann-form value Long)))))) 13 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/poly.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.poly 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann repeatedly' 5 | (t/All [x] 6 | (t/IFn 7 | [[-> x] -> (t/Seqable x)] 8 | [t/Int [-> x] -> (t/Seqable x)]))) 9 | (defn repeatedly' 10 | "Takes a function of no args, presumably with side effects, and 11 | returns an infinite (or length n if supplied) lazy sequence of calls 12 | to it" 13 | ([f] (lazy-seq (cons (f) (repeatedly' f)))) 14 | ([n f] (take n (repeatedly' f)))) 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/trans_dots.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.trans-dots 2 | (:refer-clojure :exclude [defprotocol]) 3 | (:require [clojure.core.typed :as t :refer [defprotocol inst]])) 4 | 5 | (defprotocol [x] Foo) 6 | 7 | (t/ann-datatype [x] Bar []) 8 | (deftype Bar []) 9 | 10 | (t/ann foo (t/All [x b ...] 11 | [(t/U x (Foo x) (Bar x)) ... b -> t/Any])) 12 | (defn foo [& args]) 13 | 14 | ;(defn [x b ...] foo 15 | ; [& args :- (U x Foo) ... b] :- t/Any) 16 | 17 | (inst foo t/Any) 18 | (inst foo t/Any t/Any) 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/mapv_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.mapv-test 2 | (:refer-clojure :exclude [fn]) 3 | (:require [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.test :refer :all] 5 | [clojure.core.typed :as t :refer [ann-form print-env fn]])) 6 | 7 | (deftest mapv-test 8 | (testing "when we know the input sequence has values" 9 | (is-tc-e 10 | (fn [coll :- (NonEmptySeqable String)] 11 | (let [result (mapv str coll)] 12 | (ann-form result (CountRange 1))))))) 13 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/reflect.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.reflect 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest type-reflect-test 8 | (is-tc-e #(reflect 1) [-> (Map Any Any)] 9 | :requires [[clojure.reflect :refer [reflect]]]) 10 | (is-tc-err #(reflect 1) [-> String] 11 | :requires [[clojure.reflect :refer [reflect]]])) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/gradual/import_untyped.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.gradual.import-untyped 2 | "Docstring" ;; WARNING don't change the line numbers in this file otherwise tests will fail 3 | {:lang :core.typed} 4 | (:require [clojure.core.typed :as t] 5 | [clojure.core.typed.test.gradual.untyped :as u])) 6 | 7 | (t/untyped-var u/a t/Int) 8 | (t/untyped-var u/b t/Int) 9 | 10 | (t/ann good [:-> t/Int]) 11 | (defn good [] 12 | u/a) 13 | 14 | (t/ann bad [:-> t/Int]) 15 | (defn bad [] 16 | u/b) ;; don't change this line number 17 | 18 | ;#(inc 'a) 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/succeed/CTYP49_unreachable.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.succeed.CTYP49-unreachable 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann ^:no-check request 5 | ['{:url String, :method ':get} 6 | -> (t/Atom1 '{:status Number, :body String})]) 7 | (declare request) 8 | 9 | (t/ann get-or-throw [String -> '{:status Number :body String}]) 10 | (defn get-or-throw [url] 11 | (let [doc (request {:url url :method :get}) 12 | doc @doc 13 | _ (if (not= (:status doc) 200) (throw (Exception. (str "Got bad status: " doc))))] 14 | doc)) 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/browse.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.browse 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest browse-url-test 8 | (is-tc-e #(browse-url "www.typedclojure.org") [-> Any] 9 | :requires [[clojure.java.browse :refer [browse-url]]]) 10 | (is-tc-err #(browse-url "www.typedclojure.org") [-> Boolean] 11 | :requires [[clojure.java.browse :refer [browse-url]]])) 12 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/person.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.person 2 | (:require 3 | [clojure.core.typed :refer [check-ns cf ann-datatype ann 4 | ann-protocol AnyInteger] 5 | :as t])) 6 | 7 | (t/defprotocol Age 8 | (age [this] :- Int)) 9 | 10 | (ann-datatype Person 11 | [name :- String 12 | age :- AnyInteger]) 13 | (deftype Person [name age] 14 | Age 15 | (age [this] age)) 16 | 17 | (age (Person. "Lucy" 34)) 18 | 19 | (ann my-apply (t/All [x y] [[x -> y] x -> y])) 20 | (defn my-apply [f a] 21 | (f a)) 22 | 23 | #_(my-apply age nil) 24 | -------------------------------------------------------------------------------- /src/assembly/slim.xml: -------------------------------------------------------------------------------- 1 | 2 | slim 3 | 4 | jar 5 | 6 | false 7 | 8 | 9 | src/main/clojure 10 | / 11 | 12 | 13 | src/main/cljs 14 | / 15 | 16 | 17 | src/main/java 18 | / 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_284.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-284 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed.test.test-utils :refer :all])) 4 | 5 | (deftest transitive-no-reload 6 | (is 7 | (with-typed-load 8 | (and 9 | ; bad dep throws a type error 10 | (try 11 | (require 'clojure.core.typed.test.typed-load.bad-dep :reload) 12 | nil 13 | (catch Throwable _ true)) 14 | ; but isn't rechecked by transitive dep 15 | (nil? (require 'clojure.core.typed.test.typed-load.uses-bad-dep :reload)))))) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_257.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-257 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed.checker.type-rep :as r] 4 | [clojure.core.typed.checker.type-ctors :as c] 5 | [clojure.core.typed.test.test-utils :refer :all])) 6 | 7 | (deftest empty-intersection-test 8 | (testing "empty intersection should be Top, not Bottom" 9 | (is (= (c/make-Intersection []) r/-any)) 10 | (is (= (c/In) r/-any))) 11 | (testing "intersection containing Bottom is Bottom" 12 | (is (= (c/In r/-nothing r/-any) 13 | r/-nothing)))) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/filter_combine.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.filter-combine 2 | (:require [clojure.core.typed :as t :refer [ann-form check-ns print-filterset]])) 3 | 4 | ; macroexpansion of `or` is understood 5 | (fn [a] 6 | (when (or (string? a) 7 | (symbol? a)) 8 | (ann-form a (t/U t/Sym String)))) 9 | 10 | ;exceptional control flow 11 | (fn [a] 12 | {:pre [(or (string? a) 13 | (symbol? a))]} 14 | (ann-form a (t/U t/Sym String))) 15 | 16 | ;TODO 17 | (comment 18 | (t/fn [a :- (U nil '{:d Number})] 19 | {:pre [(:d a)]} 20 | (ann-form (:d a) Number)) 21 | ) 22 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/bug1.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.bug1 2 | (:require [clojure.core.typed :as t] 3 | [clojure.core.typed.checker.type_rep]) 4 | (:import [clojure.core.typed.checker.type_rep Result] 5 | [clojure.lang Keyword])) 6 | 7 | (t/ann *frees-mode* (t/U nil t/Kw)) 8 | (def ^:dynamic *frees-mode* nil) 9 | 10 | (t/ann frees [t/Any -> t/Any]) 11 | (defmulti ^:private frees (fn [t] [*frees-mode* (class t)])) 12 | 13 | (defmethod frees [::any-var Result] 14 | [t] 15 | (t/print-env "before") 16 | (t/ann-form t Result) 17 | (let [{:keys [t fl o]} t] 18 | (t/print-env "after"))) 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/get_bounded_tvar.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.get-bounded-tvar 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defalias QuilSketch Number) 5 | 6 | (t/ann-record InkwellSketch [running? :- (t/Atom1 Boolean)]) 7 | (defrecord InkwellSketch [running?]) 8 | 9 | ; free variables bounded by a record 10 | (t/ann stop (t/All [[x :< InkwellSketch]] [x -> x])) 11 | (defn stop [sketch] 12 | (reset! (:running? sketch) false) 13 | sketch) 14 | 15 | ; free variables bounded by a HMap 16 | (t/ann f1 (t/All [[x :< '{:a (t/Atom1 Boolean)}]] [x -> x])) 17 | (defn f1 [h] 18 | (reset! (:a h) false) 19 | h) 20 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol_scoping.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol-scoping 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defprotocol NonPoly 5 | (nonpoly [this])) 6 | 7 | (t/ann-datatype DNP []) 8 | (deftype DNP [] 9 | NonPoly 10 | (nonpoly [this] this)) 11 | 12 | (t/defprotocol 13 | [[foo :variance :covariant]] 14 | Foo 15 | (bar- [this] :- foo)) 16 | 17 | (t/ann-datatype FooD [t :- t/Symbol] 18 | :extends 19 | [(Foo t/Symbol)]) 20 | 21 | (deftype FooD [t] 22 | Foo 23 | (bar- [this] t)) 24 | 25 | (t/ann-form (bar- (->FooD 'a)) 26 | t/Symbol) 27 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_37.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-37 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; this used to fail with jvm.tools.analyzer, now seems 5 | ; to type check successfully with tools.analyzer.jvm 6 | 7 | (t/defprotocol PProcess 8 | (stop [system] :- PProcess 9 | "Runs side effects to stop the process. Returns the process.")) 10 | 11 | (t/ann-record Logger [in :- t/Any 12 | out-listener :- t/Any 13 | stop :- t/Any]) 14 | (defrecord Logger [in out-listener stop] 15 | PProcess 16 | (stop [{:keys [stop] :as logger}] 17 | logger)) 18 | 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/forward_variance.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.forward-variance 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; # Problem 5 | ; 6 | ; 7 | 8 | ; TODO what happens if (def Foo) occurs in this namespaces? 9 | ;(t/declare-datatypes 10 | ; [Foo :variances [:covariant :invariant]] 11 | ; Bar) 12 | ; 13 | ;(t/declare-aliases 14 | ; [Foo :variances [:covariant :invariant] 15 | ; :rank [* * -> *]]) 16 | ; 17 | 18 | ;(binding [t/*collect-on-eval* false] 19 | ;(t/ann-datatype [[x :variance :covariant 20 | ; :< (Foo Any Any)]] 21 | ; Bar) 22 | ; 23 | ;(t/ann-datatype Foo) 24 | ;) 25 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/error_msg.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.error-msg 2 | (:require 3 | ; this loads the type system, must go first 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.test :refer :all] 6 | [clojure.core.typed :as t :refer [check-ns 7 | check-ns-info]])) 8 | 9 | (deftest invoke-line-number 10 | (is (= 11 | {:line 4 :column 2} 12 | (-> (check-ns-info 'clojure.core.typed.test.line-number) 13 | :delayed-errors 14 | first 15 | ex-data 16 | :env 17 | (select-keys [:line :column]))))) 18 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/io.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.io 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest delete-file-test 8 | (is-tc-e #(delete-file "abc") [-> Any] 9 | :requires [[clojure.java.io :refer [delete-file]]]) 10 | (is-tc-e #(delete-file "abc" true) [-> Any] 11 | :requires [[clojure.java.io :refer [delete-file]]]) 12 | (is-tc-err #(delete-file "abc") String 13 | :requires [[clojure.java.io :refer [delete-file]]])) 14 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_118_cast.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-118-cast 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann i1 String) 5 | (def i1 (cast String "a")) 6 | 7 | (t/ann i2 (t/I String (t/Value "a"))) 8 | (def i2 (let [x String] (cast x "a"))) 9 | 10 | (t/ann i3 (t/I String (t/Value "c"))) 11 | (def i3 ((t/fn [x :- Class y :- (t/Value "c")] (cast x y)) String "c")) 12 | 13 | (t/ann foo Class) 14 | (def foo String) 15 | 16 | (t/ann v (t/I String (t/Value "b"))) 17 | (def v (cast foo "b")) 18 | 19 | (t/ann v1 Class) 20 | (def v1 (cast (t/ann-form Class Class) (class :any))) 21 | 22 | (t/ann v2 String) 23 | (def v2 (cast (if true String nil) "c")) 24 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/filter_unit_tests.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.filter-unit-tests 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.checker.filter-ops :refer :all] 5 | [clojure.core.typed.checker.path-rep :refer :all] 6 | [clojure.core.typed.checker.type-ctors :refer :all])) 7 | 8 | (deftest refine-branch-test 9 | (is-tc-e (do 10 | (defalias M (U '{:a Int} 11 | '{:a Sym})) 12 | (fn [a :- M] 13 | (if (symbol? (:a a)) 14 | (ann-form (:a a) Sym) 15 | (ann-form (:a a) Int)))))) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/pred_hmap.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.pred-hmap 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defalias Cow '{:type ':cow}) 5 | (t/defalias Pig '{:type ':pig}) 6 | (t/defalias Animal (t/U Cow Pig)) 7 | 8 | (t/ann in-the-barn '[Animal Animal *]) 9 | (def in-the-barn [{:type :cow} {:type :pig}]) 10 | 11 | ;; Could cow? have automatic annotations, as it comes from core.typed? 12 | (t/ann cow? (t/Pred Cow)) 13 | (def cow? (t/pred Cow)) 14 | 15 | (t/ann cow-moo [Cow -> nil]) 16 | (defn cow-moo [cow]) 17 | 18 | (t/ann pig-oink [Pig -> nil]) 19 | (defn pig-oink [pig]) 20 | 21 | (let [a (first in-the-barn)] 22 | (if (cow? a) 23 | (cow-moo a) 24 | (pig-oink a))) 25 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/hset_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.hset-utils) 10 | 11 | (def valid-fixed? (some-fn string? symbol? keyword? nil? number? 12 | char? boolean?)) 13 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/cljc.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.cljc 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed :as t] 4 | [clojure.core.typed.load :as load])) 5 | 6 | (deftest check-ns-should-load-cljc-files 7 | (is (t/check-ns 'clojure.core.typed.test.dummy-cljc))) 8 | 9 | (deftest check-ns-should-load-clj-files-before-cljc 10 | (is (t/check-ns 'clojure.core.typed.test.duplicated))) 11 | 12 | (deftest CTYP-285-ns-form-in-reader-cond-should-work 13 | (is (thrown? 14 | clojure.lang.ExceptionInfo 15 | (load/typed-load1 "clojure/core/typed/test/ns_reader_cond")))) 16 | 17 | (deftest allow-reader-conditional-in-ns-form 18 | (is (t/check-ns 'clojure.core.typed.test.reader-cond))) 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/file_mapping.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.file-mapping 2 | (:require 3 | ; this loads the type system, must go first 4 | [clojure.core.typed.test.test-utils :refer [check clj]] 5 | [clojure.core.typed.checker.jvm.analyze-clj :as ana] 6 | [clojure.core.typed :as t] 7 | [clojure.core.typed.checker.jvm.check :as chk])) 8 | 9 | #_(-> (ana/ast-for-form '(let [a (+ 1 2)] a)) :env ((juxt :line :column))) 10 | 11 | #_(-> (ana/ast-for-form '(let [{:as a} {}] a)) :env ((juxt :line :column))) 12 | 13 | 14 | #_(clj 15 | (clojure.pprint/pprint 16 | (:file-mapping 17 | (t/check-ns-info 'clojure.core.typed.test.mapping-test-file 18 | :file-mapping true)))) 19 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/util_aliases.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.util-aliases 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defalias MyName (t/HMap :mandatory {:a (t/Value 1)})) 5 | (t/defalias MapName (t/HMap :mandatory {:a MyName})) 6 | (t/defalias MapStruct1 (t/HMap :mandatory {:type (t/Value :MapStruct1) 7 | :a MyName})) 8 | (t/defalias MapStruct2 (t/HMap :mandatory {:type (t/Value :MapStruct2) 9 | :b MyName})) 10 | (t/defalias UnionName (t/U MapStruct1 MapStruct2)) 11 | 12 | (t/defalias HMapAlias1 '{:a t/Num}) 13 | (t/defalias HMapAlias2 '{:b t/Num}) 14 | (t/defalias HMapAliasInt1 '{:foo t/Int}) 15 | (t/defalias HMapAliasStr2 '{:bar t/Str}) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP146.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP146 2 | (:require [clojure.core.typed :refer [ann] :as t])) 3 | 4 | (ann distinct-except 5 | (t/All [x] 6 | [[x -> Boolean] (t/Option (t/I clojure.lang.Sequential (t/Seq x))) -> (t/Seq x)])) 7 | (defn distinct-except 8 | "Same as distinct, but keeps duplicates if they pass exception?" 9 | [exception? [head & tail :as coll]] 10 | (lazy-seq 11 | (when head 12 | (cons head 13 | (distinct-except exception? 14 | (if (exception? head) 15 | (when tail (cast clojure.lang.Sequential tail)) 16 | (cast clojure.lang.Sequential (remove (partial = head) tail)))))))) 17 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/contract_utils_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.contract-utils-test 2 | (:refer-clojure :exclude [boolean?]) 3 | (:require [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.test :refer :all] 5 | [clojure.core.typed.contract-utils :as con :refer :all])) 6 | 7 | (deftest hmap-c-test 8 | (is ((hmap-c?) 9 | {})) 10 | (is (not ((hmap-c?) 11 | nil))) 12 | (is ((hmap-c? :k symbol?) 13 | {:k 'a})) 14 | (is (not ((hmap-c? :k symbol?) 15 | {}))) 16 | (is ((hmap-c? (optional :k) symbol?) 17 | {:k 'a})) 18 | (is (not ((hmap-c? (optional :k) symbol?) 19 | {:k :a}))) 20 | (is ((hmap-c? (optional :k) symbol?) 21 | {}))) 22 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/hsequential.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.hsequential 2 | (:require [clojure.core.typed :as t])) 3 | 4 | ; currently we can't test if (HSequential [z t/Any *]) is subtype of 5 | ; (HSequential [x y ... y]) or not, because we can't compare free variable 6 | (t/ann first-number [(t/HSequential [Number t/Any *]) -> Number]) 7 | (defn first-number [l] (first l)) 8 | 9 | ; NOTE don't write code like this, we assume one argument corresponding to one type 10 | (t/ann test-target (t/All [y ...] [Number y ... y -> (t/U nil Number)])) 11 | (defn test-target [& y] (when-not (empty? y) (first-number y))) 12 | 13 | #_(t/defn [y ...] test-target2 14 | [& y :- y ... y] :- (t/U nil Number) 15 | (when-not (empty? y) (first-number y))) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/symbolic_closures.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.symbolic-closures 2 | (:require 3 | [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.core.typed.checker.type-rep :as r] 5 | [clojure.test :refer :all])) 6 | 7 | (when r/enable-symbolic-closures? 8 | (deftest symbolic-closure-test 9 | (tc-e (let [f (fn* [x] x)] 10 | (f 1))) 11 | (tc-e (let [f (fn* [x] x)] 12 | (f 1)) 13 | Int) 14 | (tc-err (let [f (fn* [x] x)] 15 | (f 1)) 16 | Bool) 17 | #_ 18 | (tc-e (let [comp (fn* [f g] (fn* [x] (f (g x)))) 19 | f (fn* [x] x) 20 | g (fn* [y] y)] 21 | ((comp f g) 1)) 22 | ) 23 | )) 24 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/munge_record_field.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.munge-record-field 2 | (:require [clojure.core.typed :as t :refer [ann check-ns ann-form print-env cf ann-record ann-datatype]])) 3 | 4 | (ann-datatype FooDT [normal :- Number 5 | other-keys? :- Number]) 6 | (deftype FooDT [normal other-keys?]) 7 | 8 | ; don't eval this; see CLJ-979 9 | (fn [] 10 | (ann-form (.normal ^FooDT (->FooDT 2 1)) Number) 11 | ) 12 | 13 | (ann-record FooRec [other-keys? :- Number]) 14 | (defrecord FooRec [other-keys?]) 15 | 16 | ; don't eval this; see CLJ-979 17 | (fn [] 18 | (ann-form (.other-keys? ^FooDT (->FooDT 2 1)) Number) 19 | 20 | (ann-form (:other-keys? (->FooRec 1)) Number) 21 | (ann-form (.other-keys? ^FooRec (->FooRec 1)) Number) 22 | ) 23 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_258.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-258 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed.checker.type-rep :refer :all] 4 | [clojure.core.typed.checker.filter-rep :refer :all] 5 | [clojure.core.typed.checker.filter-ops :refer :all] 6 | [clojure.core.typed.test.test-utils :refer :all])) 7 | 8 | (deftest ctyp-258-test 9 | (testing "(is Any ..) = tt" 10 | (is (= (-filter -any 'a) 11 | -top))) 12 | (testing "(is Nothing ..) = ff" 13 | (is (= (-filter -nothing 'a) 14 | -bot))) 15 | (testing "(! Any ..) = ff" 16 | (is (= (-not-filter -any 'a) 17 | -bot))) 18 | (testing "(! Nothing ..) = tt" 19 | (is (= (-not-filter -nothing 'a) 20 | -top)))) 21 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_255.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-255 2 | (:require [clojure.test :refer :all] 3 | [clojure.core.typed.checker.jvm.parse-unparse :refer :all] 4 | [clojure.core.typed.checker.type-rep :as r] 5 | [clojure.core.typed.checker.type-ctors :as c] 6 | [clojure.core.typed :as t] 7 | [clojure.core.typed.checker.init :as init] 8 | [clojure.core.typed.test.test-utils :refer :all])) 9 | 10 | (deftest ctyp-255-test 11 | (testing "unknown implementation of unparse uses clojure.core.typed 12 | for special types" 13 | (is (= (unparse-type r/-any) 14 | 'clojure.core.typed/Any))) 15 | (testing "can print a tc-e result with :unknown" 16 | (is (do (prn (tc-e 1)) 17 | true)))) 18 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp_294/typed.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp-294.typed 2 | {:lang :core.typed 3 | :core.typed {:experimental #{:infer-vars 4 | :infer-locals}}} 5 | (:require 6 | [clojure.core.typed :as t] 7 | [clojure.core.typed.test.ctyp-294.untyped :as u])) 8 | 9 | #(inc (t/ann-form u/bar t/Int)) 10 | 11 | #(inc (u/foo 1)) 12 | 13 | ;#_#(inc (u/foo (inc 'a))) 14 | 15 | (t/ann bar (t/IFn ;[t/Str :-> t/Str] 16 | [t/Int :-> t/Int])) 17 | (defn bar [x] 18 | x) 19 | 20 | #(inc (bar (t/ann-form u/foo t/Int))) 21 | 22 | (map inc [u/bar]) 23 | 24 | (fn [a] (inc a)) 25 | (filter (fn [a] (inc a)) [1 2 3]) 26 | (filter (fn [a] 27 | {:pre [(integer? a)]} 28 | (inc a)) 29 | [1 2 3]) 30 | (inc @#'u/bar) 31 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/errors_ann.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.errors-ann 10 | (:require [clojure.core.typed :as t])) 11 | 12 | (t/ann ^:no-check clojure.core.typed.errors/deprecated-warn [String -> nil]) 13 | (t/ann ^:no-check clojure.core.typed.errors/int-error [String -> t/Nothing]) 14 | 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/slow.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.slow 2 | (:require 3 | [clojure.core.typed :refer [ann defalias] 4 | :as t])) 5 | 6 | (defalias VersionVector (t/NonEmptyVec Number)) 7 | (ann version-less [(t/U nil VersionVector) (t/U nil VersionVector) -> boolean]) 8 | (defn version-less 9 | "Compare two version vectors." 10 | [v1 v2] 11 | (t/loop [v1 :- (t/NilableNonEmptySeq Number) (seq v1) 12 | v2 :- (t/NilableNonEmptySeq Number) (seq v2)] 13 | (let [fv1 (first v1) 14 | fv2 (first v2)] 15 | (cond 16 | (and (not v1) (not v2)) false 17 | (and v1 (not v2)) false 18 | (or (and (not v1) v2) 19 | (and fv1 fv2 (< fv1 fv2))) true 20 | (and fv1 fv2 (> fv1 fv2)) false 21 | :else (recur (next v1) (next v2)))))) 22 | 23 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/tools_analyzer.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.tools-analyzer 2 | (:require [clojure.core.typed :as t] 3 | [clojure.core.typed.checker.jvm.analyze-clj :as ana] 4 | #_[clojure.core.typed.checker.utils :as u] 5 | #_[clojure.core.typed.current-impl :as impl])) 6 | 7 | #_(comment 8 | (defprotocol D) 9 | 10 | (-> 11 | (ana/ast-for-form 12 | '(letfn [(a [c] b) 13 | (b [c] a)])) 14 | :bindings 15 | first 16 | :init 17 | :methods 18 | first 19 | :body 20 | :ret 21 | :name 22 | ) 23 | 24 | (impl/with-clojure-impl 25 | (u/emit-form-fn 26 | (ana/ast-for-form 27 | '(fn a [b]) 28 | ))) 29 | ) 30 | 31 | ;; records 32 | (deftype FooDT3 []) 33 | (assert (cast FooDT3 (->FooDT3))) 34 | ;(assert (instance? FooDT (->FooDT))) 35 | ;(.normal ^FooDT (->FooDT 2 1)) 36 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/indirect_ann.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.indirect-ann 10 | (:require [clojure.core.typed :as t] 11 | [clojure.core.typed.checker.type-rep :as r] 12 | clojure.core.typed.checker.indirect-ops)) 13 | 14 | (t/ann clojure.core.typed.checker.indirect-ops/unparse-type [r/Type -> t/Any]) 15 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/recursive.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.recursive 2 | (:require [clojure.core.typed :as t :refer [ann-record ann-protocol]]) 3 | (:import [clojure.lang ISeq])) 4 | 5 | (t/defprotocol IValidator 6 | "Validator abstraction" 7 | (validate- [this value] :- ValidationResult 8 | "Evaluates the validator.")) 9 | 10 | (t/ann-form validate- [IValidator t/Any -> ValidationResult]) 11 | 12 | (ann-record ValidationError [validator :- IValidator 13 | value :- t/Any]) 14 | (defrecord ValidationError [validator value]) 15 | 16 | (ann-record ValidationResult 17 | [status :- (t/U ':ok ':error) 18 | result :- t/Any 19 | errors :- (t/U nil (t/Seq ValidationError)) 20 | input :- t/Any]) 21 | (defrecord ValidationResult [status result errors input]) 22 | 23 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/cast.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.cast 2 | (:refer-clojure :exclude [update cast]) 3 | (:require 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.test :refer :all] 6 | [clojure.core.typed :as tc :refer [Int cast]] 7 | )) 8 | 9 | (deftest typed-cast-test 10 | (is-tc-e (cast Int 1) Int) 11 | (is-tc-err #(cast Int (inc 'a))) 12 | (is-tc-e (cast [Int -> Int] identity) [Int -> Int]) 13 | (is-tc-e (cast '{:a Int} {:a 1}) '{:a Int}) 14 | (is-tc-e #(cast Int nil) [:-> Int]) 15 | ;; runtime errors 16 | (is (thrown? Exception (tc/check-form-info `(tc/cast tc/Int nil)))) 17 | (is (thrown? Exception 18 | (tc-e (cast '{:a Int} {:a nil})))) 19 | (is (thrown? Exception 20 | (tc-e 21 | ((:a (cast '{:a [Int :-> Int]} {:a str})) 22 | 1)))) 23 | ) 24 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/coerce_ann.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.coerce-ann 10 | (:require [clojure.core.typed :as t] 11 | clojure.core.typed.coerce-utils)) 12 | 13 | (t/ann ^:no-check clojure.core.typed.coerce-utils/Class->symbol [Class -> t/Sym]) 14 | (t/ann ^:no-check clojure.core.typed.coerce-utils/symbol->Class [t/Sym -> Class]) 15 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/local.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.local 10 | (:require [clojure.core.typed.checker.local-result :as local-result] 11 | [clojure.core.typed.checker.utils :as u])) 12 | 13 | (defn check-local [{sym :name :as expr} expected] 14 | (assoc expr 15 | u/expr-type (local-result/local-result expr sym expected))) 16 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/def_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.def-utils 10 | (:refer-clojure :exclude [defrecord defprotocol definterface]) 11 | (:require [clojure.core :as core])) 12 | 13 | (defmacro defprotocol [name & args] 14 | ;only define protocol if symbol doesn't resolve, not completely sure if this behaves like defonce 15 | (when-not (resolve name) 16 | `(core/defprotocol ~name ~@args))) 17 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/template.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.template 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest apply-template-test 7 | (is-tc-e (apply-template '[a b c d e] '[d a b e c e b a d] '(1 2 3 4 5)) 8 | :requires [[clojure.template :refer [apply-template]]]) 9 | (is-tc-e (apply-template '[a b c d e] {:a 1 :b 2 :c 3 :d 4 :e 5} '(1 2 3 4 5)) 10 | :requires [[clojure.template :refer [apply-template]]]) 11 | (is-tc-e (apply-template '[a b c d e] 3 '(1 2 3 4 5)) 12 | :requires [[clojure.template :refer [apply-template]]]) 13 | (is-tc-err (apply-template '[a b c d e] '[d a b e c e b a d] '(1 2 3 4 5)) 14 | (U (Vec Any) (HVec [Any]) (List Any)) 15 | :requires [[clojure.template :refer [apply-template]]])) 16 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/rec_protocol.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.rec-protocol 2 | (:require [clojure.core.typed :as t :refer [ann-protocol ann-datatype check-ns]])) 3 | 4 | (t/defprotocol SelfProtocol 5 | (f1 [this] :- (U nil SelfProtocol))) 6 | 7 | ;(declare-protocol 8 | ; [[f :variance :covariant]] 9 | ; HOProtocol1) 10 | ; 11 | ;Foo <: (HOProtocol2 Foo) 12 | ;Foo <: (HOProtocol2 Foo) 13 | 14 | (ann-protocol [[f :variance :covariant 15 | :< (HOProtocol2 f)]] 16 | HOProtocol2) 17 | ;my-method 18 | ; [(HOProtocol2 Id) -> 19 | ; (U (HOProtocol1 (TFn [[x :variance :covariant]] 20 | ; Integer)) 21 | ; (HOProtocol1 (TFn [[x :variance :covariant]] 22 | ; Number)))]) 23 | 24 | (ann-protocol [[f :variance :covariant 25 | :< (HOProtocol1 Any)]] 26 | HOProtocol1) 27 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_83_performance.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-83-performance 2 | (:require 3 | [clojure.core.typed :as t])) 4 | 5 | (defmacro pf [frm] 6 | frm 7 | #_`(t/print-filterset ~(str frm) ~frm)) 8 | 9 | (t/defalias VersionVector (t/NonEmptyVec Number)) 10 | (t/ann version-less [(t/U nil VersionVector) (t/U nil VersionVector) -> t/Any]) 11 | (defn version-less 12 | "Compare two version vectors." 13 | [v1 v2] 14 | (t/loop [v1 :- (t/NilableNonEmptySeq t/Num) (seq v1) 15 | v2 :- (t/NilableNonEmptySeq t/Num) (seq v2)] 16 | (let [fv1 (first v1) 17 | fv2 (first v2)] 18 | (cond 19 | (pf (and (pf (not v1)) 20 | (pf (not v2)))) false 21 | (and v1 (not v2)) false 22 | (or (and (not v1) v2) 23 | (and fv1 fv2 (< fv1 fv2))) 24 | true 25 | (and fv1 fv2 (> fv1 fv2)) false 26 | :else (recur (next v1) (next v2)) 27 | )))) 28 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/defprotocol.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.defprotocol 2 | (:refer-clojure :exclude [defprotocol fn]) 3 | (:require [clojure.core.typed :as t :refer [defprotocol fn]])) 4 | 5 | (defprotocol Foo 6 | (is-foo [this, a :- t/Num] :- t/Num) 7 | (is-bar [this, a :- t/Int] :- t/Int 8 | [this, b :- t/Num] :- t/Num) 9 | (is-baz [this, a :- t/Int] :- t/Int 10 | [this, a :- t/Int, b :- t/Int] :- t/Int 11 | [this, a :- t/Int, b :- t/Int, c :- t/Int] :- t/Int)) 12 | 13 | (defprotocol DocD 14 | "This is a docstring" 15 | (docd [this, a :- t/Num] :- t/Num 16 | "trailing docstring")) 17 | 18 | (fn [a :- Foo] 19 | (is-foo a 1)) 20 | 21 | (fn [a :- Foo] :- t/Int 22 | (is-bar a 1)) 23 | 24 | (fn [a :- Foo] :- t/Num 25 | (is-bar a 1.1)) 26 | 27 | (fn [a :- Foo] :- t/Int 28 | (is-baz a 1)) 29 | 30 | (fn [a :- Foo] :- t/Int 31 | (is-baz a 1 1)) 32 | 33 | (fn [a :- Foo] :- t/Int 34 | (is-baz a 1 1 1)) 35 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/binding.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.binding 10 | (:require [clojure.core.typed.util-vars :as vs] 11 | [clojure.core.typed.checker.utils :as u])) 12 | 13 | (defn check-binding 14 | [check {:keys [init] :as expr} expected] 15 | (let [cinit (binding [vs/*current-expr* init] 16 | (check init expected))] 17 | (assoc expr 18 | :init cinit 19 | u/expr-type (u/expr-type cinit)))) 20 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/quote.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.quote 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.checker.check.const :as const])) 12 | 13 | (defn check-quote [check constant-type {:keys [expr] :as quote-expr} expected] 14 | (let [cexpr (const/check-const constant-type true expr expected)] 15 | (assoc quote-expr 16 | :expr cexpr 17 | u/expr-type (u/expr-type cexpr)))) 18 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/multi_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.multi-utils 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.checker.type-rep :as r])) 12 | 13 | (defonce ^:dynamic *current-mm* nil) 14 | (set-validator! #'*current-mm* (some-fn nil? 15 | (con/hmap-c? :dispatch-fn-type r/Type? 16 | :dispatch-val-ret r/TCResult?))) 17 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/tap.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.tap 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | (deftest print-tap-diagnostic-test 8 | (is-tc-e #(print-tap-diagnostic "abc") [-> Any] 9 | :requires [[clojure.test.tap :refer [print-tap-diagnostic]]]) 10 | (is-tc-err #(print-tap-diagnostic 1) [-> Any] 11 | :requires [[clojure.test.tap :refer [print-tap-diagnostic]]])) 12 | 13 | (deftest print-tap-plan-test 14 | (is-tc-e #(print-tap-plan 1) [-> Any] 15 | :requires [[clojure.test.tap :refer [print-tap-plan]]])) 16 | 17 | (deftest print-tap-pass-test 18 | (is-tc-e #(print-tap-pass 1) [-> Any] 19 | :requires [[clojure.test.tap :refer [print-tap-pass]]])) 20 | 21 | (deftest print-tap-fail-test 22 | (is-tc-e #(print-tap-fail 1) [-> Any] 23 | :requires [[clojure.test.tap :refer [print-tap-fail]]])) 24 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/records.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.records 2 | (:require [clojure.core.typed :refer [check-ns ann-record ann-form cf]] 3 | [clojure.repl :refer [pst]])) 4 | 5 | (set! *warn-on-reflection* true) 6 | 7 | (ann-record MyRecord [a :- Number]) 8 | 9 | (defrecord MyRecord [a] 10 | Object 11 | (toString [this] nil)) 12 | 13 | (ann-form (:a (->MyRecord 1)) Number) 14 | (ann-form (map->MyRecord {:a 2}) MyRecord) 15 | 16 | (ann-form (let [^MyRecord r (MyRecord. 1)] 17 | (.a r)) 18 | Number) 19 | 20 | (let [^MyRecord r (MyRecord. 1)] 21 | (ann-form (.a r) Number)) 22 | 23 | (let [r (MyRecord. 1)] 24 | (ann-form (.a r) Number)) 25 | 26 | (ann-form (assoc (->MyRecord 1) :a 1) 27 | MyRecord) 28 | 29 | #_(ann-form (assoc (->MyRecord 1) :a 'a) MyRecord) 30 | 31 | #_(do 32 | (defrecord A [a] 33 | clojure.lang.IFn 34 | (invoke [this query] (get this query))) 35 | (ann-record A [a :- Number])) 36 | 37 | (ann-record [[a :variance :covariant]] 38 | MyPolyRecord [a :- Number]) 39 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/reset_caches.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.jvm.reset-caches 10 | (:require [clojure.core.typed.checker.jvm.subtype :as sub] 11 | [clojure.core.typed.checker.type-ctors :as c] 12 | [clojure.core.typed.checker.cs-gen :as cgen])) 13 | 14 | (defn reset-caches 15 | "Reset internal type caches." 16 | [] 17 | (sub/reset-subtype-cache) 18 | (c/reset-Un-cache) 19 | (c/reset-In-cache) 20 | (c/reset-supers-cache!) 21 | (c/reset-RClass-of-cache!) 22 | (cgen/reset-dotted-var-store!) 23 | nil) 24 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/CTYP_144.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.CTYP-144 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.core.typed.checker.jvm.analyze-clj :as ana] 4 | [clojure.test :refer :all])) 5 | 6 | (deftest instance-method-test 7 | (is-tc-e 8 | (do (defprotocol IRandom 9 | (-next-int 10 | [this limit :- Integer] :- Integer)) 11 | 12 | (ann-record SeededRandom [seed :- Int 13 | rng :- java.util.Random]) 14 | 15 | (defrecord SeededRandom [seed ^java.util.Random rng] 16 | IRandom 17 | (-next-int 18 | [this limit] 19 | (ann-form limit Integer)))))) 20 | 21 | #_(defprotocol IRandom 22 | (-next-int [this limit])) 23 | 24 | #_(-> 25 | (ana/ast-for-form 26 | '(defrecord SeededRandom [seed ^java.util.Random rng] 27 | IRandom 28 | (-next-int [this limit]))) 29 | :body 30 | :statements 31 | (nth 2) 32 | :methods 33 | (nth 29) 34 | :methods 35 | first 36 | keys 37 | ) 38 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/assoc.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.assoc 2 | (:require 3 | [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.core.typed :refer [ann-form check-ns] :as t] 5 | [clojure.test :refer :all]) 6 | (:import (clojure.lang Symbol))) 7 | 8 | (deftest assoc-test 9 | (is-tc-e (assoc {:a 1} :b 2) 10 | '{:a Number :b Number}) 11 | 12 | (is-tc-err #(let [a 1] 13 | (assoc a :b 2))) 14 | (is-tc-err 15 | (do (t/ann-record FooRec [a :- t/Num 16 | b :- t/Symbol]) 17 | (defrecord FooRec [a b]) 18 | (assoc (->FooRec 1 'a) :a 'b))) 19 | 20 | (is-tc-e 21 | (do (t/ann-record FooRec [a :- t/Num 22 | b :- t/Symbol]) 23 | (defrecord FooRec [a b]) 24 | (assoc (->FooRec 1 'a) :a 4))) 25 | 26 | ;intersections 27 | (is-tc-e (t/fn [m :- (t/I (t/HMap :mandatory {:foo Num}) 28 | (t/HMap :mandatory {:bar Num}))] 29 | :- '{:foo Num, :bar Num, :baz Num} 30 | (assoc m :baz 2)))) 31 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/set_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.set-test 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.test :refer :all])) 4 | 5 | (deftest construct-hset 6 | (is-tc-e #{1 2 3} 7 | :expected 8 | (HSet #{1 2 3})) 9 | (is-tc-e #{1 nil} 10 | :expected 11 | (HSet #{nil 1}))) 12 | 13 | (deftest upcast-hset 14 | (is-tc-e #{1 2 3} 15 | :expected 16 | (Set Num)) 17 | (is-tc-e (conj #{1 2 3} 1) 18 | :expected 19 | (Set Num))) 20 | 21 | (deftest set-pred-test 22 | (is-tc-e (let [foo :- (U false nil ':a ':b), :a] 23 | (if (#{:a :b false nil} foo) 24 | (ann-form foo (U ':a ':b)) 25 | (ann-form foo (U false nil))))) 26 | (is-tc-e (let [foo :- (U false nil ':a ':b), :a] 27 | (when (#{:a :b nil} foo) 28 | (ann-form foo (U ':a ':b))))) 29 | (is-tc-e (let [foo :- (U nil ':a ':b), :a] 30 | (when (#{:a :b nil} foo) 31 | (ann-form foo (U ':a ':b)))))) 32 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/indirect_ops.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.indirect-ops 10 | (:require [clojure.core.typed.checker.indirect-utils :as in])) 11 | 12 | (in/make-indirection unparse-type 13 | parse-type 14 | check-funapp 15 | assoc-pairs-noret 16 | subtype? 17 | -FS 18 | -top-fn 19 | -empty-fn 20 | infer 21 | PropEnv? 22 | -or 23 | -and 24 | type-of-nofail) 25 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/atom.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.atom 2 | (:require [clojure.core.typed :as t :refer [ann ann-form check-ns cf defalias]] 3 | [clojure.repl :refer [pst]]) 4 | (:import (clojure.lang IPersistentMap Symbol))) 5 | 6 | (ann my-atom (t/Atom1 Number)) 7 | (def my-atom (atom 2)) 8 | 9 | (reset! my-atom 1) 10 | (swap! my-atom (t/fn [x :- Number] (+ x 2 3))) 11 | 12 | (defalias InnerEntry '{:c '{:d String}}) 13 | (defalias Entry '{:a '{:b (IPersistentMap Symbol (t/Atom1 InnerEntry))}}) 14 | 15 | (ann complicated (t/Atom1 Entry)) 16 | (def complicated (atom {:a {:b {}}})) 17 | 18 | ;(swap! complicated update-in [:a :b 'a] #(swap! (or % (atom {})) assoc-in [:c :d] "b")) 19 | 20 | (swap! complicated (ann-form 21 | (fn [c] 22 | (-> c 23 | (update-in [:a :b 'a] 24 | (fn [a] (swap! (or a (atom {})) 25 | (fn [i] 26 | (-> i (assoc-in [:c :d] "b")))))))) 27 | [Entry -> Entry])) 28 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ring.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ring 2 | (:require [clojure.core.typed :refer [ann check-ns ann-form print-env cf]]) 3 | (:import (clojure.lang IPersistentMap IPersistentVector))) 4 | 5 | (comment 6 | (ann assoc-conj 7 | (All [x] (Fn [(IPersistentMap Any (U x (IPersistentVector x))) Any x -> 8 | (IPersistentMap Any (U x (IPersistentVector x)))] 9 | [(IPersistentVector (U x (IPersistentVector x))) Integer x -> 10 | (IPersistentVector (U x (IPersistentVector x)))]))) 11 | (defn assoc-conj 12 | "Associate a key with a value in a map. If the key already exists in the map, 13 | a vector of values is associated with the key." 14 | [map key val] 15 | (ann-form map (IPersistentMap Any (U x (IPersistentVector x)))) 16 | (print-env "top") 17 | (assoc map key 18 | (if-let [cur (get map key)] 19 | (do 20 | (print-env "map") 21 | (if (vector? cur) 22 | (do (print-env "cur") 23 | (conj cur val)) 24 | [cur val]) 25 | ) 26 | val))) 27 | 28 | (check-ns) 29 | ) 30 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/poly_record.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.poly-record 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/ann-record [[foo :variance :invariant]] Foo [b :- (t/U nil Number)]) 5 | (t/tc-ignore 6 | (defrecord Foo [b]) 7 | ) 8 | 9 | (comment 10 | (defmacro defrecord> 11 | "Define a typed record. 12 | 13 | eg. ;monomorphic 14 | (defrecord> FooM [a :- (U nil Number), 15 | b :- Number] 16 | Object 17 | (toString [this] \"\")) 18 | 19 | ;polymorphic 20 | (defrecord> [[x :variance :covariant]] 21 | FooP [a :- x, 22 | b :- Number] 23 | Object 24 | (toString [this] \"\"))" 25 | [& args] 26 | (let [vbnd (when (vector? (first args)) 27 | (first args)) 28 | args (if vbnd 29 | (next args) 30 | args) 31 | [nme fields & args] args] 32 | `(do (ann-record 33 | ~@(concat (when vbnd 34 | [vbnd]) 35 | nme 36 | fields)) 37 | (defrecord ~nme ~(mapv first (partition 3 fields)) 38 | ~@args)))) 39 | ) 40 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/pomegranate.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.pomegranate 2 | (:import (clojure.lang Named)) 3 | (:require [clojure.core.typed :as t])) 4 | 5 | #_(t/non-nil-return java.lang.Class/getDeclaredMethod :all) 6 | #_(t/nilable-param java.lang.reflect.Method/invoke {2 #{0}}) 7 | 8 | (t/ann call-method [Class Named (t/Vec Class) (t/U nil Object) (t/U nil Object) * -> (t/U nil Object)]) 9 | 10 | ;; call-method pulled from clojure.contrib.reflect, (c) 2010 Stuart Halloway & Contributors 11 | (defn call-method 12 | "Calls a private or protected method. 13 | 14 | params is a vector of classes which correspond to the arguments to 15 | the method e 16 | 17 | obj is nil for static methods, the instance object otherwise. 18 | 19 | The method-name is given a symbol or a keyword (something Named)." 20 | [^Class klass method-name params obj & args] 21 | (let [method (doto (.getDeclaredMethod klass 22 | (name method-name) 23 | (t/into-array> Class params)) 24 | (.setAccessible true))] 25 | (.invoke method obj (t/into-array> (t/U nil Object) args)))) 26 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/contract_ann.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.contract-ann 10 | (:require [clojure.core.typed :as t])) 11 | 12 | (t/ann ^:no-check clojure.core.typed.contract-utils/nat? [t/Any * -> Boolean]) 13 | (t/ann ^:no-check clojure.core.typed.contract-utils/hash-c? [[t/Any -> t/Any] [t/Any -> t/Any] -> [t/Any -> t/Any]]) 14 | ;can't express alternating args 15 | (t/ann ^:no-check clojure.core.typed.contract-utils/hmap-c? [t/Any * -> [t/Any -> t/Any]]) 16 | (t/ann ^:no-check clojure.core.typed.contract-utils/set-c? [[t/Any -> t/Any] -> [t/Any -> t/Any]]) 17 | (t/ann ^:no-check clojure.core.typed.contract-utils/every-c? [[t/Any -> t/Any] -> [(t/U nil (t/Seqable t/Any)) -> t/Any]]) 18 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/reflect_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.jvm.reflect-utils 10 | (:require [clojure.reflect :as reflect] 11 | [clojure.string :as str]) 12 | (:import (clojure.lang RT))) 13 | 14 | (defn reflect 15 | [obj & options] 16 | (apply reflect/type-reflect (if (class? obj) obj (class obj)) 17 | :reflector (reflect/->JavaReflector (RT/baseLoader)) 18 | options)) 19 | 20 | (defn reflect-friendly-sym [cls] 21 | (-> (reflect/typename cls) 22 | (str/replace "[]" "<>") 23 | symbol)) 24 | 25 | (defn pprint-reflection-sym [cls] 26 | (-> (reflect/typename cls) 27 | (str/replace "<>" "[]") 28 | symbol)) 29 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol_untyped_extend.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol-untyped-extend 2 | (:require [clojure.core.typed :refer [ann-protocol tc-ignore 3 | ann-datatype ann check-ns] 4 | :as t] 5 | [clojure.core.typed.test.protocol-in-another-ns 6 | :refer [AnotherNs baz]])) 7 | 8 | (t/defprotocol IFoo 9 | (bar [this])) 10 | 11 | (ann-datatype Bar []) 12 | (deftype Bar []) 13 | 14 | (extend-protocol IFoo 15 | Bar 16 | (bar [b] 'a) 17 | 18 | nil 19 | (bar [c] 'd)) 20 | 21 | (ann takes-IFoo [IFoo -> t/Any]) 22 | (defn takes-IFoo [f] 23 | (bar f)) 24 | 25 | ; don't eval; see CLJ-979 26 | (fn [] (takes-IFoo (->Bar))) 27 | 28 | ;; Annotate protocol in another ns 29 | 30 | (ann-protocol clojure.core.typed.test.protocol-in-another-ns/AnotherNs 31 | baz 32 | [AnotherNs -> t/Any]) 33 | 34 | (extend-protocol AnotherNs 35 | Bar 36 | (baz [this] nil)) 37 | 38 | (ann takes-AnotherNs [AnotherNs -> t/Any]) 39 | (defn takes-AnotherNs [a] 40 | (baz a)) 41 | 42 | ; don't eval; see CLJ-979 43 | (fn [] 44 | (takes-AnotherNs (->Bar))) 45 | 46 | ;; A protocol that extends 47 | 48 | ;(deftype Pair [a] 49 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/nilsafe_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.nilsafe-utils 10 | (:require [clojure.set :as set] 11 | [clojure.core.typed :as t])) 12 | 13 | (t/ann ^:no-check set-union 14 | (t/All [x] 15 | (t/IFn [-> (t/Set x)] 16 | [(t/U nil (t/Set x)) -> (t/Set x)] 17 | [(t/U nil (t/Set x)) (t/Set x) * -> (t/Set x)]))) 18 | (def set-union (fnil set/union #{})) 19 | 20 | (t/ann ^:no-check set-difference 21 | (t/All [x] 22 | (t/IFn [(t/U nil (t/Set x)) -> (t/Set x)] 23 | [(t/U nil (t/Set x)) (t/Set t/Any) * -> (t/Set x)]))) 24 | (def set-difference (fnil set/difference #{})) 25 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/invoke.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.invoke 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.checker.check.funapp :as funapp])) 12 | 13 | (defn normal-invoke [check-fn expr fexpr args expected & {:keys [cfexpr cargs]}] 14 | (let [cfexpr (or cfexpr 15 | (check-fn fexpr)) 16 | cargs (or cargs 17 | (mapv check-fn args)) 18 | ftype (u/expr-type cfexpr) 19 | argtys (map u/expr-type cargs) 20 | actual (funapp/check-funapp fexpr args ftype argtys expected :check-fn check-fn)] 21 | (assoc expr 22 | :fn cfexpr 23 | :args cargs 24 | u/expr-type actual))) 25 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/rclass_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.jvm.rclass-env 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.checker.type-rep :as r])) 12 | 13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14 | ;; Restricted Class 15 | 16 | ;Class -> RClass 17 | (defonce RESTRICTED-CLASS (atom {})) 18 | (set-validator! RESTRICTED-CLASS (con/hash-c? symbol? r/Type?)) 19 | 20 | (defn get-rclass 21 | "Returns the RClass with class symbol csym. 22 | Returns nil if not found." 23 | [csym] 24 | (@RESTRICTED-CLASS csym)) 25 | 26 | (defn alter-class* [csym type] 27 | (assert (r/Type? type) 28 | (str "alter-class* " csym " not a type: " type)) 29 | (swap! RESTRICTED-CLASS assoc csym type)) 30 | 31 | (defn reset-rclass-env! [m] 32 | (reset! RESTRICTED-CLASS m) 33 | nil) 34 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/protocol.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.protocol 2 | (:require [clojure.core.typed :as t :refer [ann-protocol ann-datatype check-ns]])) 3 | 4 | (t/defprotocol AddProtoc 5 | (adder [this amount :- t/Num] :- t/Num)) 6 | 7 | (ann-datatype Accumulator [t :- Number]) 8 | (deftype Accumulator [t] 9 | AddProtoc 10 | (adder [_ i] 1)) 11 | 12 | (ann-protocol short/ShortNs) 13 | 14 | ;; polymorphic protocols 15 | 16 | (t/defprotocol 17 | [[x :variance :covariant]] 18 | IFoo 19 | (bar [this] :- t/Num) 20 | (baz [this] :- t/Any)) 21 | 22 | ;TODO 23 | ;(ann-datatype FooPoly [] 24 | ; :unchecked-ancestors 25 | ; [(IFoo Any)]) 26 | ;(deftype FooPoly [] 27 | ; IFoo 28 | ; (bar [_] 1)) 29 | 30 | ;#(bar (FooPoly.)) 31 | ; 32 | ;;; extend a polymophic protocol after deftype definition 33 | ; 34 | ;(ann-datatype FooLatePoly []) 35 | ;(deftype FooLatePoly []) 36 | ; 37 | ;(extend-type FooLatePoly 38 | ; IFoo 39 | ; (bar [this] 1)) 40 | 41 | ; annotate first position in methods 42 | (t/defalias FunctorLB 43 | (t/TFn [[x :variance :covariant]] 44 | t/Nothing)) 45 | 46 | (t/defprotocol [[F :variance :covariant, 47 | :> FunctorLB 48 | :< Functor]] 49 | Functor 50 | ([a b c ...] fmap [fv :- (F a), g :- [a :-> b]] :- (F b))) 51 | 52 | (comment 53 | (check-ns 'clojure.core.typed.test.protocol) 54 | ) 55 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/set_bang.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.set-bang 10 | (:require [clojure.core.typed.util-vars :as vs] 11 | [clojure.core.typed.checker.utils :as u] 12 | [clojure.core.typed.checker.check.utils :as cu] 13 | [clojure.core.typed.checker.type-rep :as r] 14 | [clojure.core.typed.checker.jvm.parse-unparse :as prs] 15 | [clojure.core.typed.errors :as err] 16 | [clojure.core.typed.checker.jvm.subtype :as sub])) 17 | 18 | (defn check-set! [check {:keys [target val env] :as expr} expected] 19 | (binding [vs/*current-expr* expr 20 | vs/*current-env* env] 21 | (let [ctarget (check target expected) 22 | cval (check val (u/expr-type ctarget))] 23 | (assoc expr 24 | u/expr-type (u/expr-type cval) 25 | :target ctarget 26 | :val cval)))) 27 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/csgen_intersection.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.csgen-intersection 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.checker.cs-gen :as cgen] 5 | )) 6 | 7 | (deftest csgen-intersect 8 | (is-tc-e (do 9 | (defprotocol 10 | [[x :variance :covariant]] 11 | ICollection') 12 | (defprotocol 13 | [[x :variance :covariant]] 14 | ISeq') 15 | (defprotocol 16 | [[x :variance :covariant]] 17 | ISeqable') 18 | (defprotocol 19 | [[x :variance :covariant]] 20 | IList') 21 | (defalias 22 | NEColl' 23 | (TFn [[x :variance :covariant]] 24 | (ICollection' x))) 25 | (defalias 26 | NEASeq' 27 | (TFn [[x :variance :covariant]] 28 | (I 29 | (ICollection' x) 30 | (ISeqable' x) 31 | (ISeq' x) 32 | (IList' x) 33 | #_(CountRange 1)))) 34 | (fn [seq' :- (All [x] [(NEColl' x) -> (NEASeq' x)]) 35 | a :- (NEColl' Int)] 36 | :- (NEASeq' Number) 37 | (seq' a))))) 38 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/array_old.clj: -------------------------------------------------------------------------------- 1 | ; some old tests that don't type check anymore but look useful 2 | (ns clojure.core.typed.test.array-old 3 | (:require [clojure.core.typed :refer [ann check-ns into-array> cf print-env ann-form] 4 | :as t] 5 | [clojure.repl :refer [pst]])) 6 | 7 | (ann my-integer-array [-> (Array Integer)]) 8 | (defn my-integer-array [] (into-array> Integer (map int [1 2]))) 9 | 10 | (ann my-int-array [-> (Array int)]) 11 | (defn my-int-array [] (into-array> int (map int [1 2]))) 12 | 13 | (ann sum [(ReadOnlyArray Number) -> Number]) 14 | (defn sum [arr] 15 | (t/loop [idx :- long 0, 16 | ret :- Number 0] 17 | (if (< idx (alength arr)) 18 | (recur 19 | (unchecked-inc idx) 20 | (+ (aget arr idx) ret)) 21 | ret))) 22 | 23 | (fn [] (sum (my-integer-array))) 24 | 25 | (ann write-integer-to-zero [(Array2 Integer t/Any) -> nil]) 26 | (defn write-integer-to-zero [arr] 27 | (aset arr 0 (int 12)) 28 | nil) 29 | 30 | (ann write-int-to-zero [(Array2 int t/Any) -> nil]) 31 | (defn write-int-to-zero [arr] 32 | (aset arr 0 (int 12)) 33 | nil) 34 | 35 | (fn [] (write-integer-to-zero my-integer-array)) 36 | (fn [] (write-int-to-zero (my-int-array))) 37 | 38 | (ann bad-modify-array [(Array Number) -> nil]) 39 | #_(defn bad-modify-array [ar] 40 | (let [ar2 (ann-form ar (Array2 Number Object))] 41 | (aset ar2 0 (new java.util.Observable)) 42 | nil)) 43 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/multi.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.multi 10 | (:require [clojure.core.typed.checker.fold-rep :as fold] 11 | [clojure.core.typed.checker.type-rep :as r]) 12 | (:import (clojure.core.typed.checker.type_rep Function))) 13 | 14 | ;; Multimethod definition 15 | 16 | (def ExpectedDispatchType ::expected-dispatch-type) 17 | 18 | (fold/derive-default ExpectedDispatchType) 19 | 20 | (fold/add-fold-case ExpectedDispatchType 21 | Function 22 | (fn [ty _] 23 | (assoc ty :rng (r/make-Result r/-any)))) 24 | 25 | ;return the expected type for the dispatch fn of the given multimethod's expected type 26 | ;[Type -> Type] 27 | (defn expected-dispatch-type [mm-type] 28 | {:pre [(r/AnyType? mm-type)] 29 | :post [(r/AnyType? %)]} 30 | (fold/fold-rhs ExpectedDispatchType 31 | {:type-rec expected-dispatch-type} 32 | mm-type)) 33 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/unsound_simplify.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.unsound-simplify 2 | (:require [clojure.core.typed :refer [ann ann-datatype check-ns cf] 3 | :as t]) 4 | (:import (clojure.lang Symbol))) 5 | 6 | (t/defprotocol 7 | [[a :variance :covariant]] 8 | P1 9 | (get-p1 [this] :- a)) 10 | 11 | (t/defprotocol 12 | [[a :variance :covariant]] 13 | P2 14 | (get-p2 [this] :- a)) 15 | 16 | (ann ^:no-check P1? (t/Pred (P1 t/Any))) 17 | (defn P1? [a] 18 | (satisfies? P1 a)) 19 | 20 | (ann ^:no-check P2? (t/Pred (P2 t/Any))) 21 | (defn P2? [a] 22 | (satisfies? P2 a)) 23 | 24 | (ann foo [(t/U (P1 Number) (P2 Number)) -> (t/U nil Number)]) 25 | (defn foo [p] 26 | (when (P1? p) 27 | (get-p1 p))) 28 | 29 | (ann-datatype [[a :variance :covariant]] 30 | T1 31 | [p :- a] 32 | :unchecked-ancestors [(P1 a)]) 33 | (deftype T1 [p] 34 | P1 35 | (get-p1 [this] p)) 36 | 37 | (ann-datatype [[a :variance :covariant]] 38 | T2 39 | [p :- a] 40 | :unchecked-ancestors [(P2 a)]) 41 | (deftype T2 [p] 42 | P2 43 | (get-p2 [this] p)) 44 | 45 | (ann-datatype [[a :variance :covariant]] 46 | T3 47 | [p :- a] 48 | :unchecked-ancestors [(P1 a) 49 | (P2 Symbol)]) 50 | (deftype T3 [p] 51 | P1 52 | (get-p1 [this] 'a) 53 | P2 54 | (get-p2 [this] p)) 55 | 56 | (foo (->T1 1)) 57 | (foo (->T2 2)) 58 | (foo (->T3 2)) 59 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/repl_new.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.repl-new 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest apropos-test 7 | (is-tc-e #(apropos "clojure") [-> (Seq Sym)] 8 | :requires [[clojure.repl :refer [apropos]]]) 9 | (is-tc-e #(apropos #"") [-> (Seq Sym)] 10 | :requires [[clojure.repl :refer [apropos]]]) 11 | (is-tc-err #(apropos "clojure") [-> (Seq String)] 12 | :requires [[clojure.repl :refer [apropos]]]) 13 | (is-tc-err #(apropos 'clojure) [-> (Seq Str)] 14 | :requires [[clojure.repl :refer [apropos]]])) 15 | 16 | (deftest demunge-test 17 | (is-tc-e #(demunge "clojure.repl$demunge") [-> Str] 18 | :requires [[clojure.repl :refer [demunge]]]) 19 | (is-tc-err #(demunge "clojure.repl$demunge") [-> (Vec Any)] 20 | :requires [[clojure.repl :refer [demunge]]]) 21 | (is-tc-err #(demunge 'clojure.repl$demunge) [-> Str] 22 | :requires [[clojure.repl :refer [demunge]]])) 23 | 24 | (deftest source-fn-test 25 | (is-tc-e #(source-fn 'source) [-> (U nil Str)] 26 | :requires [[clojure.repl :refer [source-fn]]]) 27 | (is-tc-err #(source-fn 'source) [-> (Vec Any)] 28 | :requires [[clojure.repl :refer [source-fn]]]) 29 | (is-tc-err #(source-fn "source") [-> Str] 30 | :requires [[clojure.repl :refer [source-fn]]])) 31 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/tag_test.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.tag-test 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.test :refer :all])) 4 | 5 | ;(deftest tag-test 6 | ; (is-tc-e (tag 1 long)) 7 | ; (is-tc-err (tag 1 Long)) 8 | ; (is-tc-e (tag 9 | ; (let [a (inc 1) 10 | ; b (* 2 10)] 11 | ; (+ a b)) 12 | ; long))) 13 | ; 14 | ;(deftest unboxed-arith-test 15 | ; (is-tc-e (do 16 | ; ;from http://stackoverflow.com/questions/11824815/fast-complex-number-arithmetic-in-clojure 17 | ; (ann-datatype complex [real :- Double 18 | ; imag :- Double]) 19 | ; (deftype complex [^double real 20 | ; ^double imag]) 21 | ; 22 | ; (ann plus [complex complex -> complex]) 23 | ; (defn plus [^complex z1 ^complex z2] 24 | ; (let [x1 (double (.real z1)) 25 | ; y1 (double (.imag z1)) 26 | ; x2 (double (.real z2)) 27 | ; y2 (double (.imag z2))] 28 | ; (tag 29 | ; (complex. (ann-form 30 | ; (tag 31 | ; (+ (tag x1 double) 32 | ; (tag x2 double)) 33 | ; double) 34 | ; Double) 35 | ; (+ y1 y2)) 36 | ; complex)))))) 37 | ; 38 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp97_tvar_scoping.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp97-tvar-scoping 2 | (:import (clojure.lang ASeq LazySeq)) 3 | (:require [clojure.core.typed :as t 4 | :refer [ann Seqable]])) 5 | 6 | (ann reduce_ (t/All [a b] 7 | (t/IFn 8 | [[a b -> b] b (Seqable a) -> b] 9 | [[a (Seqable (t/U a b)) -> (Seqable (t/U a b))] 10 | (Seqable (t/U a b)) (Seqable a) -> (Seqable (t/U a b))]))) 11 | (defn reduce_ 12 | [f zero coll] 13 | (if-let [s (seq coll)] 14 | (f (first s) 15 | (reduce_ f zero (rest s))) 16 | zero)) 17 | 18 | (ann append_ (t/All [a b] [(Seqable a) (Seqable b) -> (t/U (Seqable (t/U a b)) 19 | (ASeq (t/U a b)))])) 20 | (defn append_ 21 | [coll1 coll2] 22 | (reduce_ (t/inst cons (t/U a b)) coll2 coll1)) 23 | 24 | 25 | ; -------- main 26 | 27 | ; if you comment out this function, you will get :ok 28 | (ann map-1 (t/All [a b] [[a -> b] (Seqable a) 29 | -> (LazySeq b)])) 30 | (defn map-1 [f coll] 31 | (lazy-seq 32 | (if-let [s (seq coll)] 33 | (cons (f (first s)) 34 | (map-1 f (rest s)))))) 35 | 36 | (ann map-2 (t/All [a b] [[a -> b] (Seqable a) -> (LazySeq b)])) 37 | (defn map-2 38 | [f coll] 39 | (lazy-seq 40 | (reduce_ (t/fn [x :- a ; ERROR!! -- Cannot resolve type: a 41 | y :- (Seqable b)] 42 | (append_ [(f x)] y)) 43 | [] 44 | coll))) 45 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/dvar_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.dvar-env 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.contract-utils :as con] 12 | [clojure.core.typed :as t]) 13 | (:import [clojure.lang Symbol] 14 | [clojure.core.typed.checker.type_rep F])) 15 | 16 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 17 | ;; Dotted Variable Environment 18 | 19 | ;symbol -> F 20 | (t/ann *dotted-scope* (t/Map Symbol F)) 21 | (defonce ^:dynamic *dotted-scope* {}) 22 | (set-validator! #'*dotted-scope* (con/hash-c? symbol? r/F?)) 23 | 24 | (t/ann bound-index? [t/Any -> t/Any]) 25 | (defn bound-index? [n] 26 | (contains? *dotted-scope* n)) 27 | 28 | (defmacro with-dotted [dvars & body] 29 | `(with-dotted-mappings (into {} (for [v# ~dvars] 30 | [(:name v#) v#])) 31 | ~@body)) 32 | 33 | (defmacro with-dotted-mappings [dvar-map & body] 34 | `(binding [*dotted-scope* (merge *dotted-scope* ~dvar-map)] 35 | ~@body)) 36 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/method_override_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.method-override-env 10 | (:require [clojure.core.typed.env :as env] 11 | [clojure.core.typed.current-impl :as impl] 12 | [clojure.core.typed.checker.type-rep :as r])) 13 | 14 | ; Should only override a method with a more specific type 15 | ; eg. 16 | 17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 18 | ;; Method Override Env 19 | 20 | (def add-method-override impl/add-method-override) 21 | 22 | (defn reset-method-override-env! [m] 23 | (env/swap-checker! assoc impl/method-override-env-kw m) 24 | nil) 25 | 26 | (defn merge-method-override-env! [m] 27 | {:pre [(map? m)]} 28 | (env/swap-checker! update impl/method-override-env-kw merge m) 29 | nil) 30 | 31 | (defn method-override-env [] 32 | {:post [(map? %)]} 33 | (get (env/deref-checker) impl/method-override-env-kw {})) 34 | 35 | (defn get-method-override [m] 36 | {:post [((some-fn r/Poly? r/FnIntersection? nil?) %)]} 37 | (force (get (method-override-env) m))) 38 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/method_return_nilables.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.method-return-nilables 10 | (:require [clojure.core.typed.env :as env] 11 | [clojure.core.typed.current-impl :as impl])) 12 | 13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14 | ;; Method Return non-nilables 15 | 16 | (def add-nonnilable-method-return impl/add-nonnilable-method-return) 17 | 18 | (defn reset-nonnilable-method-return-env! [m] 19 | (env/swap-checker! assoc impl/method-return-nonnilable-env-kw m) 20 | nil) 21 | 22 | (defn merge-nonnilable-method-return-env! [m] 23 | {:pre [(map? m)]} 24 | (env/swap-checker! update impl/method-return-nonnilable-env-kw merge m) 25 | nil) 26 | 27 | (defn nonnilable-method-return-env [] 28 | {:post [(map? %)]} 29 | (get (env/deref-checker) impl/method-return-nonnilable-env-kw {})) 30 | 31 | (defn nonnilable-return? [sym arity] 32 | (let [as (get (nonnilable-method-return-env) sym)] 33 | (boolean (or (= :all as) 34 | (when as 35 | (as arity)))))) 36 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/ns_options.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.ns-options 10 | (:require [clojure.core.typed :as t] 11 | [clojure.core.typed.current-impl :as impl] 12 | [clojure.core.typed.env :as env])) 13 | 14 | (t/defalias NsOptions 15 | "Options for namespaces" 16 | (t/HMap :optional 17 | {:warn-on-unannotated-vars Boolean})) 18 | 19 | (t/defalias OptMap 20 | (t/Map t/Sym NsOptions)) 21 | 22 | (t/ann reset-ns-opts! [-> nil]) 23 | (defn reset-ns-opts! [] 24 | (env/swap-checker! assoc impl/ns-opts-kw {}) 25 | nil) 26 | 27 | (t/ann ^:no-check register-warn-on-unannotated-vars [t/Sym -> nil]) 28 | (def register-warn-on-unannotated-vars impl/register-warn-on-unannotated-vars) 29 | 30 | (defn get-ns-opts [nsym] 31 | {:post [(map? %)]} 32 | (get-in (env/deref-checker) [impl/ns-opts-kw nsym] {})) 33 | 34 | (t/ann ^:no-check warn-on-unannotated-vars? [t/Sym -> Boolean]) 35 | (defn warn-on-unannotated-vars? [nsym] 36 | (boolean (:warn-on-unannotated-vars (get-ns-opts nsym)))) 37 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/string.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.string 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest escape-test 7 | (is-tc-e (escape "I want 1 < 2 as HTML, & other good things." 8 | {\< "&", \> "&", \& "&"}) String 9 | :requires [[clojure.string :refer [escape]]]) 10 | (is-tc-e (escape "I want 1 < 2 as HTML, & other good things." 11 | (fn [a] 12 | (case a 13 | \< "&" 14 | \> "&" 15 | \& "&" 16 | nil))) 17 | String 18 | :requires [[clojure.string :refer [escape]]]) 19 | (is-tc-err (escape "I want 1 < 2 as HTML, & other good things." 20 | {\< "&", \> "&", \& "&"}) Boolean 21 | :requires [[clojure.string :refer [escape]]]) 22 | (is-tc-err (escape 1 {\< "&", \> "&", \& "&"}) String 23 | :requires [[clojure.string :refer [escape]]])) 24 | 25 | (deftest split-lines-test 26 | (is-tc-e (split-lines "abc\n abc") (Vec String) 27 | :requires [[clojure.string :refer [split-lines]]]) 28 | (is-tc-err (split-lines "abc\n abc") Boolean 29 | :requires [[clojure.string :refer [split-lines]]]) 30 | (is-tc-err (split-lines 1) (Vec String) 31 | :requires [[clojure.string :refer [split-lines]]])) 32 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/contrib_annotations.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.contrib-annotations 10 | (:require [clojure.core.typed :as t :refer [ann-protocol ann]])) 11 | 12 | (ann-protocol clojure.java.io/IOFactory 13 | make-reader 14 | [clojure.java.io/IOFactory '{:append t/Any, :encoding (t/U nil String)} -> java.io.BufferedReader] 15 | 16 | make-writer 17 | [clojure.java.io/IOFactory '{:append t/Any, :encoding (t/U nil String)} -> java.io.BufferedWriter] 18 | 19 | make-input-stream 20 | [clojure.java.io/IOFactory '{:append t/Any, :encoding (t/U nil String)} -> java.io.BufferedInputStream] 21 | 22 | make-output-stream 23 | [clojure.java.io/IOFactory '{:append t/Any, :encoding (t/U nil String)} -> java.io.BufferedOutputStream]) 24 | 25 | (ann ^:no-check clojure.java.io/reader 26 | [clojure.java.io/IOFactory -> java.io.BufferedReader]) 27 | (ann ^:no-check clojure.java.io/writer 28 | [clojure.java.io/IOFactory -> java.io.BufferedWriter]) 29 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/ctor_override_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.ctor-override-env 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.env :as env] 12 | [clojure.core.typed.current-impl :as impl] 13 | [clojure.core.typed.checker.type-rep :as r])) 14 | 15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16 | ;; Constructor Override Env 17 | 18 | (def add-constructor-override impl/add-constructor-override) 19 | 20 | (defn reset-constructor-override-env! [m] 21 | (env/swap-checker! assoc impl/constructor-override-env-kw m) 22 | nil) 23 | 24 | (defn merge-constructor-override-env! [m] 25 | {:pre [(map? m)]} 26 | (env/swap-checker! update impl/constructor-override-env-kw merge m) 27 | nil) 28 | 29 | (defn constructor-override-env [] 30 | {:post [(map? %)]} 31 | (get (env/deref-checker) impl/constructor-override-env-kw {})) 32 | 33 | (defn get-constructor-override [sym] 34 | {:post [((some-fn nil? r/Type?) %)]} 35 | (force (get (constructor-override-env) sym))) 36 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/stacktrace.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.stacktrace 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest e-test 7 | (is-tc-e #(e) [-> Any] 8 | :requires [[clojure.stacktrace :refer [e]]])) 9 | 10 | (deftest print-cause-trace-test 11 | (is-tc-e #(print-cause-trace (Exception. "a")) [-> Any] 12 | :requires [[clojure.stacktrace :refer [print-cause-trace]]]) 13 | (is-tc-err #(print-cause-trace "A") [-> Any] 14 | :requires [[clojure.stacktrace :refer [print-cause-trace]]])) 15 | 16 | (deftest print-stack-trace-test 17 | (is-tc-e #(print-stack-trace (Exception. "a")) [-> Any] 18 | :requires [[clojure.stacktrace :refer [print-stack-trace]]]) 19 | (is-tc-err #(print-stack-trace "AC") [-> Any] 20 | :requires [[clojure.stacktrace :refer [print-stack-trace]]])) 21 | 22 | (deftest print-throwable-test 23 | (is-tc-e #(print-throwable (Exception. "a")) [-> Any] 24 | :requires [[clojure.stacktrace :refer [print-throwable]]]) 25 | (is-tc-err #(print-throwable "A") [-> Any] 26 | :requires [[clojure.stacktrace :refer [print-throwable]]])) 27 | 28 | (deftest root-cause-test 29 | (is-tc-e #(root-cause (Exception. "a")) [-> Throwable] 30 | :requires [[clojure.stacktrace :refer [root-cause]]]) 31 | (is-tc-err #(root-cause (Exception. "a")) [-> Exception] 32 | :requires [[clojure.stacktrace :refer [root-cause]]])) 33 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/monitor.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.monitor 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.util-vars :as vs] 12 | [clojure.core.typed.checker.type-rep :as r] 13 | [clojure.core.typed.checker.type-ctors :as c] 14 | [clojure.core.typed.checker.jvm.subtype :as sub] 15 | [clojure.core.typed.checker.check.utils :as cu] 16 | [clojure.core.typed.checker.filter-ops :as fo] 17 | [clojure.core.typed.checker.check-below :as below])) 18 | 19 | (defn check-monitor 20 | "monitor-enter and monitor-exit both take any object and return nil" 21 | [check {:keys [target] :as expr} expected] 22 | {:pre [((some-fn nil? r/TCResult?) expected)]} 23 | (binding [vs/*current-expr* expr] 24 | (assoc expr 25 | :target (check target (r/ret (c/RClass-of Object))) 26 | u/expr-type (below/maybe-check-below (r/ret r/-nil (fo/-false-filter)) 27 | expected)))) 28 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/edn_parser.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.edn-parser 2 | "Tools for loading runtime settings." 3 | (:require [clojure.edn :as edn] 4 | [clojure.java.io :as io] 5 | [clojure.core.typed :as t]) 6 | (:import (java.io PushbackReader Reader))) 7 | 8 | 9 | (t/ann clojure.java.io/reader [t/Any -> Reader]) 10 | ;FIXME needs more cases 11 | (t/ann clojure.edn/read [PushbackReader -> t/Any]) 12 | 13 | (t/defalias Settings (t/Map t/Kw t/Any)) 14 | 15 | (t/ann defaults Settings) 16 | (def ^:private defaults 17 | "A set of default settings values" 18 | {}) 19 | 20 | (t/ann settings (t/Atom1 (t/U Settings nil))) 21 | (def ^:private settings 22 | "This atom hosts the loaded settings." 23 | (atom nil)) 24 | 25 | (t/ann typed-read [PushbackReader -> Settings]) 26 | (t/tc-ignore 27 | (defn typed-read [r] 28 | (edn/read r)) 29 | ) 30 | 31 | (defn- load-settings 32 | "load the settings map for this application" 33 | [] 34 | (with-open 35 | [r (PushbackReader. (io/reader 36 | (or (System/getenv "KODIAK_SETTINGS") 37 | "settings.edn")))] 38 | (reset! settings (typed-read r)))) 39 | 40 | (t/ann load-settings [-> t/Any]) 41 | 42 | (t/ann read-setting [clojure.lang.Keyword -> t/Any]) 43 | (defn read-setting 44 | "reads a setting from the configuration file (defined by the environment 45 | variable KODIAK_SETTINGS), loading it if necessary." 46 | [skey] 47 | (when-not @settings (load-settings)) 48 | (or (when-let [s @settings] (get s skey)) 49 | (get defaults skey))) 50 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/vector.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.vector 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.checker.check-below :as below] 12 | [clojure.core.typed.checker.utils :as u] 13 | [clojure.core.typed.checker.jvm.subtype :as sub] 14 | [clojure.core.typed.checker.check.utils :as cu] 15 | [clojure.core.typed.checker.filter-ops :as fo])) 16 | 17 | (defn check-vector [check {:keys [items] :as expr} expected] 18 | {:post [(-> % u/expr-type r/TCResult?) 19 | (vector? (:items %))]} 20 | (let [cargs (mapv check items) 21 | res-type (r/-hvec (mapv (comp r/ret-t u/expr-type) cargs) 22 | :filters (mapv (comp r/ret-f u/expr-type) cargs) 23 | :objects (mapv (comp r/ret-o u/expr-type) cargs))] 24 | (assoc expr 25 | :items cargs 26 | u/expr-type (below/maybe-check-below 27 | (r/ret res-type (fo/-true-filter)) 28 | expected)))) 29 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/method_param_nilables.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.method-param-nilables 10 | (:require [clojure.core.typed.env :as env] 11 | [clojure.core.typed.current-impl :as impl])) 12 | 13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14 | ;; Method Param nilables 15 | 16 | (defn reset-method-nilable-param-env! [m] 17 | (env/swap-checker! assoc impl/method-param-nilable-env-kw m) 18 | nil) 19 | 20 | (defn merge-method-nilable-param-env! [m] 21 | {:pre [(map? m)]} 22 | (env/swap-checker! update impl/method-param-nilable-env-kw merge m) 23 | nil) 24 | 25 | (def add-method-nilable-param impl/add-method-nilable-param) 26 | 27 | (defn nilable-param-env [] 28 | {:post [(map? %)]} 29 | (get (env/deref-checker) impl/method-param-nilable-env-kw {})) 30 | 31 | (defn nilable-param? [sym arity param] 32 | (boolean 33 | (when-let [nilables (get (nilable-param-env) sym)] 34 | (when-let [params (or (nilables :all) 35 | (nilables arity))] 36 | (or (#{:all} params) 37 | (params param)))))) 38 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/javadoc.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.javadoc 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.core.typed.test.destructure])) 6 | 7 | 8 | (deftest javadoc-test 9 | (is-tc-e #(javadoc 1) [-> Any] 10 | :requires [[clojure.java.javadoc :refer [javadoc]]])) 11 | 12 | (deftest add-local-javadoc-test 13 | (is-tc-e #(add-local-javadoc 1) [-> (List Any)] 14 | :requires [[clojure.java.javadoc :refer [add-local-javadoc]]]) 15 | (is-tc-err #(add-local-javadoc 1) [-> String] 16 | :requires [[clojure.java.javadoc :refer [add-local-javadoc]]])) 17 | 18 | (deftest add-remote-javadoc-test 19 | (is-tc-e #(add-remote-javadoc 20 | "org.apache.commons.csv." 21 | "http://commons.apache.org/proper/commons-csv/apidocs/index.html") 22 | [-> (Map Any Any)] 23 | :requires [[clojure.java.javadoc :refer [add-remote-javadoc]]]) 24 | (is-tc-err #(add-remote-javadoc 25 | "org.apache.commons.csv." 26 | "http://commons.apache.org/proper/commons-csv/apidocs/index.html") 27 | [-> String] 28 | :requires [[clojure.java.javadoc :refer [add-remote-javadoc]]]) 29 | (is-tc-err #(add-remote-javadoc 30 | 1 31 | "http://commons.apache.org/proper/commons-csv/apidocs/index.html") 32 | [-> (Map Any Any)] 33 | :requires [[clojure.java.javadoc :refer [add-remote-javadoc]]])) 34 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/throw.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.throw 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.checker.check-below :as below] 12 | [clojure.core.typed.checker.filter-ops :as fo] 13 | [clojure.core.typed.checker.type-ctors :as c] 14 | [clojure.core.typed.checker.filter-rep :as fl] 15 | [clojure.core.typed.checker.object-rep :as obj] 16 | [clojure.core.typed.checker.utils :as u])) 17 | 18 | (defn check-throw 19 | [check {:keys [exception] :as expr} expected exception-expected] 20 | {:pre [((some-fn nil? r/TCResult?) exception-expected)]} 21 | (let [cexception (check exception exception-expected) 22 | ret (below/maybe-check-below 23 | (r/ret (c/Un) 24 | (fo/-unreachable-filter) 25 | obj/-empty 26 | ;never returns normally 27 | (r/-flow fl/-bot)) 28 | expected)] 29 | (assoc expr 30 | :exception cexception 31 | u/expr-type ret))) 32 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/catch.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.catch 10 | (:require [clojure.core.typed.current-impl :as impl] 11 | [clojure.core.typed.errors :as err] 12 | [clojure.core.typed.checker.utils :as u] 13 | [clojure.core.typed.checker.type-ctors :as c] 14 | [clojure.core.typed.checker.lex-env :as lex] 15 | [clojure.core.typed.analyzer :as ana2] 16 | [clojure.core.typed.ast-utils :as ast-u])) 17 | 18 | (defn check-catch [check {handler :body :keys [local] :as expr} expected] 19 | (let [expr (-> expr 20 | (update :class ana2/run-passes)) 21 | ecls (ast-u/catch-op-class expr) 22 | local-sym (:name local) 23 | local-type (impl/impl-case 24 | :clojure (c/RClass-of-with-unknown-params ecls) 25 | :cljs (err/nyi-error "catch in CLJS")) 26 | chandler (lex/with-locals {local-sym local-type} 27 | (check handler expected))] 28 | (assoc expr 29 | :body chandler 30 | u/expr-type (u/expr-type chandler)))) 31 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/check_ns_clj.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.check-ns-clj 10 | (:require [clojure.core.typed.errors :as err] 11 | [clojure.core.typed.current-impl :as impl] 12 | [clojure.core.typed.checker.check-ns-common :as chk-ns])) 13 | 14 | (defn check-ns-info 15 | "Same as check-ns, but returns a map of results from type checking the 16 | namespace. 17 | 18 | Options 19 | - :collect-only Don't type check the given namespace/s, but collect the 20 | top level type annotations like ann, ann-record. 21 | - :type-provided? If true, use the expected type to check the form 22 | - :file-mapping If true, return map provides entry :file-mapping, a hash-map 23 | of (Map '{:line Int :column Int :file Str} Str). 24 | 25 | Deprecated: 26 | - :profile Use Timbre to profile the type checker. Timbre must be 27 | added as a dependency." 28 | [ns-or-syms opt] 29 | (chk-ns/check-ns-info impl/clojure ns-or-syms opt)) 30 | 31 | (defn check-ns 32 | [ns-or-syms opt] 33 | (chk-ns/check-ns impl/clojure ns-or-syms opt)) 34 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/seq_ops.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.seq-ops 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.checker.type-ctors :as c] 12 | [clojure.core.typed :as t] 13 | [clojure.core.typed.checker.jvm.parse-unparse :as prs] 14 | [clojure.core.typed.checker.jvm.subtype :as sub] 15 | [clojure.core.typed.errors :as err] 16 | )) 17 | 18 | (defn type-to-seq [t] 19 | {:pre [(r/Type? t)]} 20 | (cond 21 | (r/Union? t) (apply c/Un (map type-to-seq (:types t))) 22 | (r/Intersection? t) (apply c/In (map type-to-seq (:types t))) 23 | (r/HSequential? t) (if (seq (:types t)) 24 | t 25 | (c/Un r/-nil t)) 26 | ;TODO (sub/subtype? t (prs/parse-type `(t/U nil t/Seqable t/Any))) 27 | :else (err/int-error (str "Cannot create seq from " t)))) 28 | 29 | (defn cons-types [a d] 30 | {:pre [(r/Type? a) 31 | (r/Type? d)]} 32 | (assert nil "TODO") 33 | ) 34 | 35 | (defn concat-types [& ts] 36 | {:pre [(every? r/Type? ts)]} 37 | (assert nil "TODO") 38 | ) 39 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/indirect_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | ;platform independent indirection utilities 10 | (ns clojure.core.typed.checker.indirect-utils) 11 | 12 | (defmacro make-indirection [& vs] 13 | `(do 14 | ~@(map (fn [v] 15 | (let [atm (symbol (str v "-atom"))] 16 | (when-not (resolve v) 17 | [`(def ~atm (atom nil)) 18 | `(def ~v (fn [& args#] 19 | (let [i# (deref ~atm)] 20 | (when-not i# 21 | (throw (ex-info (str "Indirection for " 22 | '~(symbol (str (ns-name *ns*)) (str v)) 23 | " not set") 24 | {}))) 25 | (apply i# args#))))]))) 26 | vs))) 27 | 28 | (defmacro add-indirection [i var] 29 | `(reset! ~(symbol (str i "-atom")) 30 | ; saves getting stung by var reloading 31 | ; Could just use a var, but we want to work on CLJS 32 | (fn [& args#] 33 | (apply ~var args#)))) 34 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/special/tc_ignore.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.special.tc-ignore 10 | (:require [clojure.core.typed :as t] 11 | [clojure.core.typed.checker.check-below :as below] 12 | [clojure.core.typed.util-vars :as vs] 13 | [clojure.core.typed.checker.utils :as u] 14 | [clojure.core.typed.analyzer :as ana2] 15 | [clojure.core.typed.checker.type-rep :as r])) 16 | 17 | (defn check-tc-ignore [check {:keys [statements] :as expr} expected] 18 | {:pre [(#{3} (count statements))]} 19 | (binding [vs/*current-expr* expr] 20 | (let [expr (-> expr 21 | ana2/run-passes 22 | ; ensure the main checking loop doesn't reevaluate this tc-ignore, 23 | ; since run-passes has already if this is top-level. 24 | ana2/unmark-eval-top-level)] 25 | (assoc expr 26 | ::t/tc-ignore true 27 | u/expr-type (below/maybe-check-below 28 | (r/ret r/-any) 29 | ;TODO use :form in 3rd statment to enhance expected error msg 30 | expected))))) 31 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/jvm/array.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.jvm.array 2 | (:require [clojure.core.typed :refer [ann check-ns into-array> cf print-env ann-form] 3 | :as t] 4 | [clojure.core.typed.test.test-utils :refer :all] 5 | [clojure.test :refer :all] 6 | )) 7 | 8 | (deftest array-test 9 | (is-clj (= (Class/forName "[I") 10 | (eval `(class (t/into-array> ~'int [1]))))) 11 | (is-clj (clj (= (Class/forName "[Ljava.lang.Object;") 12 | (eval `(class (t/into-array> (t/U nil ~'int) [1])))))) 13 | (is-clj (clj (= (Class/forName "[Ljava.lang.Number;") 14 | (eval `(class (t/into-array> (t/U nil Number) [1])))))) 15 | (is-clj (clj (= (Class/forName "[Ljava.lang.Object;") 16 | (eval `(class (t/into-array> (t/U t/Sym Number) [1])))))) 17 | (is-clj (= (Class/forName "[Ljava.lang.Object;") 18 | (eval `(class (t/into-array> Object (t/U t/Sym Number) [1]))))) 19 | ) 20 | 21 | (deftest array-primitive-hint-test 22 | (is-tc-e (let [^ints a (t/into-array> int [(int 1)])] 23 | (alength a)))) 24 | 25 | ; FIXME this is wrong, should not just be nil 26 | #_(deftest array-first-test 27 | (is-cf (let [a (clojure.core.typed/into-array> Long [1 2])] 28 | (first a)))) 29 | 30 | (deftest array-reflection-test 31 | (is-tc-e (fn make-process [script] 32 | {:post [%]} 33 | (let [^Runtime r (Runtime/getRuntime) 34 | _ (assert r) 35 | ^"[Ljava.lang.String;" arr (into-array> String ["echo 'hello'"])] 36 | (.exec r arr))) 37 | [String -> java.lang.Process])) 38 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/ctyp105.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.ctyp105 2 | (:require [clojure.string :as str] 3 | [clojure.core.typed :as t])) 4 | 5 | (t/defalias PatInfo 6 | (t/HMap :mandatory {:ptnt_nr String} 7 | :optional {:ptnt_vertrekdatum String 8 | :ptnt_voorv2denaam String 9 | :ptnt_tweedenaam String 10 | :ptnt_fullname String 11 | :ptnt_roepnaam String 12 | :roepnaam String 13 | :ptnt_geboren String 14 | :geboortedatum String 15 | :ptnt_voorletters String 16 | :voorletters String 17 | :ptnt_voorveigen String 18 | :voorvoegsel String 19 | :actief Boolean 20 | :achternaam String 21 | :ptnt_ruiter String 22 | :sms_status String 23 | })) 24 | 25 | (t/ann ptnt-check-ruiters [PatInfo -> PatInfo]) 26 | (defn ptnt-check-ruiters 27 | "Check the SMS-status of a patient. 28 | :sms_satus Status will be set to 'ON', 'OFF' or ''" 29 | [rec] 30 | (let [smsStat (if-let [ruiters (:ptnt_ruiter rec)] 31 | (let [ruiters (str/upper-case ruiters)] 32 | (if (re-find #"\*SN" ruiters) 33 | "Off" 34 | (if (re-find #"\*SO" ruiters) 35 | "On" 36 | "?"))) 37 | "?")] 38 | (t/ann-form rec PatInfo) 39 | (assoc (t/ann-form (dissoc rec :ptnt_ruiter) PatInfo) 40 | :sms_status (str smsStat)))) 41 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/recur_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.check.recur-utils 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.checker.type-rep :as r])) 12 | 13 | (u/def-type RecurTarget [dom rest drest kws] 14 | "A target for recur" 15 | [(every? r/Type? dom) 16 | ((some-fn nil? r/Type?) rest) 17 | ((some-fn nil? r/DottedPretype?) drest) 18 | (nil? kws)]) ;TODO 19 | 20 | (defmacro ^:private set-validator-doc! [var val-fn] 21 | `(set-validator! ~var (fn [a#] (assert (~val-fn a#) 22 | (str "Invalid reference state: " ~var 23 | " with value: " 24 | (pr-str a#))) 25 | true))) 26 | 27 | (defonce ^:dynamic *recur-target* nil) 28 | (set-validator-doc! #'*recur-target* (some-fn nil? RecurTarget?)) 29 | 30 | (defmacro with-recur-target [tgt & body] 31 | `(binding [*recur-target* ~tgt] 32 | ~@body)) 33 | 34 | (defonce ^:dynamic *loop-bnd-anns* nil) 35 | (set-validator! #'*loop-bnd-anns* #(or (nil? %) 36 | (every? r/Type? %))) 37 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/collect_utils.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.collect-utils 10 | (:require [clojure.core.typed.checker.type-ctors :as c] 11 | [clojure.core.typed.checker.type-rep :as r])) 12 | 13 | (defn protocol-method-var-ann [mt names bnds] 14 | (cond 15 | (r/Poly? mt) (let [outer-names names 16 | inner-names (concat (c/Poly-fresh-symbols* mt))] 17 | (c/Poly* (concat outer-names inner-names) 18 | (concat bnds (c/Poly-bbnds* inner-names mt)) 19 | (c/Poly-body* inner-names mt) 20 | :named (:named mt))) 21 | 22 | (r/PolyDots? mt) (let [outer-names names 23 | inner-names (concat (c/PolyDots-fresh-symbols* mt))] 24 | (c/PolyDots* (concat outer-names inner-names) 25 | (concat bnds (c/PolyDots-bbnds* inner-names mt)) 26 | (c/PolyDots-body* inner-names mt) 27 | :named (:named mt))) 28 | :else (let [outer-names names] 29 | (c/Poly* outer-names 30 | bnds 31 | mt)))) 32 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/instant.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.instant 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest read-instant-date-test 7 | (is-tc-e (read-instant-date "2014-04-23T10:13Z") java.util.Date 8 | :requires [[clojure.instant :refer [read-instant-date]]]) 9 | (is-tc-err (read-instant-date "2014-04-23T10:13Z") String 10 | :requires [[clojure.instant :refer [read-instant-date]]]) 11 | (is-tc-err (read-instant-date 201404231013) java.util.Date 12 | :requires [[clojure.instant :refer [read-instant-date]]])) 13 | 14 | (deftest read-instant-calendar-test 15 | (is-tc-e (read-instant-calendar "2014-04-23T10:13Z") java.util.GregorianCalendar 16 | :requires [[clojure.instant :refer [read-instant-calendar]]]) 17 | (is-tc-err (read-instant-calendar "2014-04-23T10:13Z") String 18 | :requires [[clojure.instant :refer [read-instant-calendar]]]) 19 | (is-tc-err (read-instant-calendar 201404231013) java.util.GregorianCalendar 20 | :requires [[clojure.instant :refer [read-instant-calendar]]])) 21 | 22 | (deftest read-instant-timestamp-test 23 | (is-tc-e (read-instant-timestamp "2014-04-23T10:13Z") java.sql.Timestamp 24 | :requires [[clojure.instant :refer [read-instant-timestamp]]]) 25 | (is-tc-err (read-instant-timestamp "2014-04-23T10:13Z") String 26 | :requires [[clojure.instant :refer [read-instant-timestamp]]]) 27 | (is-tc-err (read-instant-timestamp 201404231013) java.sql.Timestamp 28 | :requires [[clojure.instant :refer [read-instant-timestamp]]])) 29 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/mm.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.mm 2 | (:require [clojure.core.typed :as t])) 3 | 4 | (t/defalias Expr 5 | (t/U '{:op ':test1 6 | :a Number 7 | :b Number} 8 | '{:op ':test2})) 9 | 10 | (t/ann single-dispatch [Expr -> t/Any]) 11 | 12 | ; Expected type for :op 13 | ; -> (All [x] [t/Any -> x :object {:id 0 :path [(Key :op)]} 14 | (defmulti single-dispatch :op) 15 | 16 | ; check a has been refined correctly 17 | (defmethod single-dispatch :test1 18 | [a] 19 | (t/ann-form a '{:op ':test1})) 20 | 21 | (t/ann multi-dipatch [Expr Expr -> t/Any]) 22 | (defmulti multi-dipatch (fn [a b] 23 | [(:op a) (:op b)])) 24 | 25 | (defmethod multi-dipatch [:test1 :test2] 26 | [a b] 27 | (t/ann-form a '{:op ':test1}) 28 | (t/ann-form b '{:op ':test2})) 29 | 30 | (defmethod multi-dipatch :default 31 | [a b] 32 | ; this shouldn't emit a warning about ClassPE 33 | 'foo) 34 | 35 | (t/ann-datatype FooDT []) 36 | (deftype FooDT []) 37 | 38 | (t/ann-record FooRec [a :- Number]) 39 | (defrecord FooRec [a]) 40 | 41 | (t/ann multi-dipatch2 [t/Any -> t/Any]) 42 | (defmulti multi-dipatch2 (fn [a] 43 | [(+ 2 3 4 2) (class a)])) 44 | 45 | (defmethod multi-dipatch2 [1 Number] 46 | [a] 47 | (t/ann-form a Number) 48 | (+ 1 a)) 49 | 50 | (defmethod multi-dipatch2 [1 FooDT] [a] (t/ann-form a FooDT)) 51 | (defmethod multi-dipatch2 [1 FooRec] [a] (t/ann-form a FooRec)) 52 | (defmethod multi-dipatch2 [::anyfoo FooRec] [a] (t/ann-form a FooRec)) 53 | 54 | (defmethod multi-dipatch2 [::anyfoo FooRec] 55 | [{:keys [a]}] 56 | (t/ann-form a Number)) 57 | 58 | (defmethod multi-dipatch2 [::anyfoo FooRec] 59 | [arg] 60 | (t/ann-form arg FooRec) 61 | (let [{:keys [a]} arg] 62 | (t/ann-form a Number))) 63 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/fn.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.check.fn 10 | (:require [clojure.core.typed :as t] 11 | [clojure.core.typed.checker.type-rep :as r] 12 | [clojure.core.typed.checker.utils :as u] 13 | [clojure.core.typed.checker.filter-ops :as fo] 14 | [clojure.core.typed.checker.filter-rep :as fl] 15 | [clojure.core.typed.checker.object-rep :as obj] 16 | [clojure.core.typed.checker.check.fn-methods :as fn-methods] 17 | [clojure.core.typed.checker.check.utils :as cu])) 18 | 19 | ;[FnExpr (Option Type) -> Expr] 20 | (defn check-fn 21 | "Check a fn to be under expected and annotate the inferred type" 22 | [{:keys [methods] :as fexpr} expected] 23 | {:pre [(r/TCResult? expected) 24 | (#{:fn} (:op fexpr))] 25 | :post [(-> % u/expr-type r/TCResult?) 26 | (vector? (::t/cmethods %))]} 27 | ;(prn "check-fn" methods) 28 | (let [{:keys [ifn methods cmethods]} 29 | (fn-methods/check-fn-methods 30 | methods 31 | (r/ret-t expected) 32 | :self-name (cu/fn-self-name fexpr))] 33 | (assoc fexpr 34 | :methods methods 35 | ::t/cmethods cmethods 36 | u/expr-type (r/ret ifn (fo/-true-filter))))) 37 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/with_meta.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.with-meta 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.errors :as err] 12 | [clojure.core.typed.checker.utils :as u])) 13 | 14 | (defn visit-tail-pos [ast f] 15 | (let [rec #(visit-tail-pos % f)] 16 | (case (:op ast) 17 | :do (update ast :ret rec) 18 | ;; would be ambiguous when calculating whether to erase the :with-meta node 19 | :if (err/int-error "Not allowed :with-meta around :if") 20 | (:let :letfn) (update ast :body rec) 21 | ;; probably possible to handle, but seems likely to never occur in practice 22 | :with-meta (err/int-error "Not allowed nested :with-meta") 23 | (f ast)))) 24 | 25 | (defn check-with-meta 26 | [check {:keys [expr meta] :as with-meta-expr} expected] 27 | {:post [(-> % u/expr-type r/TCResult?)]} 28 | (let [erase-atom (atom nil) 29 | expr (visit-tail-pos expr (fn [ast] 30 | (assoc ast ::erase-atom erase-atom))) 31 | cexpr (check expr expected) 32 | cmeta (check meta)] 33 | (if @erase-atom 34 | cexpr 35 | (assoc with-meta-expr 36 | :expr cexpr 37 | :meta cmeta 38 | u/expr-type (u/expr-type cexpr))))) 39 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/kw_args.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.kw-args 2 | (:require [clojure.core.typed :refer [ann check-ns ann-form cf] :as t])) 3 | 4 | (ann empty-kw [& :optional {} -> nil]) 5 | (defn empty-kw [& {:as opts}] 6 | nil) 7 | 8 | (ann foo-kw [& :optional {:a Number} -> (t/U nil Number)]) 9 | (defn foo-kw [& {:keys [a]}] 10 | (when a 11 | (inc a))) 12 | 13 | (fn [] (foo-kw :a 1)) 14 | ;(fn [] (foo-kw :a 'a)) 15 | 16 | (ann foo-arg-kw [Number & :optional {:a Number} -> (t/U nil Number)]) 17 | (defn foo-arg-kw [c & {:keys [a]}] 18 | (when a 19 | (inc a))) 20 | 21 | ;(fn [] (foo-arg-kw 1 2 :a 1)) 22 | (fn [] (foo-arg-kw 1 :a 1)) 23 | 24 | (ann poly-foo-kw (t/All [x] 25 | [& :optional {:a x} -> (t/U nil x)])) 26 | (defn poly-foo-kw [& {:keys [a]}] 27 | a) 28 | 29 | (ann-form (poly-foo-kw :a 1) 30 | (t/U nil Number)) 31 | (ann-form (poly-foo-kw :a 'a) 32 | (t/U nil clojure.lang.Symbol)) 33 | 34 | (ann poly-foo-mandatory-kw (t/All [x] 35 | [& :mandatory {:a x} -> x])) 36 | (defn poly-foo-mandatory-kw [& {:keys [a]}] 37 | a) 38 | 39 | (ann-form (poly-foo-mandatory-kw :a 'a) 40 | clojure.lang.Symbol) 41 | (ann-form (poly-foo-mandatory-kw :a 1) 42 | Number) 43 | 44 | ;(ann poly-kw-variance (t/All [x] 45 | ; [& {:a x :b [x -> t/Any]} -> t/Any])) 46 | ; What happens if we don't supply a :b parameter? Is `x` detected to be contravariant? It should probably be invariant 47 | 48 | (ann test-non-value-kw [& :optional {:a [t/Any -> t/Any]} -> t/Any]) 49 | (defn test-non-value-kw [& {:keys [a]}] a) 50 | 51 | (test-non-value-kw :a (fn [a] a)) 52 | 53 | ; keyword map is a (union of) complete hash-map(s) 54 | 55 | (ann test-complete-hmap [& :optional {:a Number} -> t/Any]) 56 | (defn test-complete-hmap [& {:keys [a]}] 57 | (ann-form a (t/U nil Number))) 58 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/cps.clj: -------------------------------------------------------------------------------- 1 | ;https://gist.github.com/3191865 2 | ; 3 | ;(defn cpf [f priority] 4 | ; (fn [k & args] 5 | ; (js/setTimeout #(k (apply f args)) priority))) 6 | ; 7 | ;(def sqrt #(Math/sqrt %)) 8 | ; 9 | ;(defn pyth 10 | ; "Calculate the hypotenuse of a right triangle." 11 | ; [x y] 12 | ; (sqrt (+ (* x x) (* y y)))) 13 | ; 14 | ;(defn pyth& 15 | ; "Calculate the hypotenuse of a right triangle: continuation passing style (CPS) version. 16 | ; 17 | ; Represents a green thread. k is the function to invoke with the 18 | ; final result; priority is the number of milliseconds to wait between 19 | ; continuation invocations. 20 | ; 21 | ; One can imagine a macro for converting pyth to pyth&. 22 | ; 23 | ; One can also imagine a mechanism, involving the cpf function above, 24 | ; for maintaining outstanding green threads and their associated 25 | ; timeouts and continuations. One might use .clearInterval to pause a 26 | ; thread, restarting it by invoking the last reified continuation in 27 | ; that thread. 28 | ; 29 | ; One may also involve a scheduler that prioritizes or deprioritizes 30 | ; outstanding threads by some heuristic. 31 | ; 32 | ; This system could allow us to use futures, promises, and blocking 33 | ; derefs on green threads without blocking the entire browser in 34 | ; ClojureScript programs." 35 | ; [x y k priority] 36 | ; ((cpf * priority) 37 | ; (fn [x2] 38 | ; ((cpf * priority) 39 | ; (fn [y2] 40 | ; ((cpf + priority) 41 | ; (fn [x2py2] 42 | ; ((cpf sqrt priority) k x2py2)) x2 y2)) y y)) x x)) 43 | ; 44 | ;(do 45 | ; (pyth& 1 2 #(.log js/console (str "thread 0: " %)) 500) 46 | ; (pyth& 1 2 #(.log js/console (str "thread 1: " %)) 100) 47 | ; (pyth& 1 2 #(.log js/console (str "thread 2: " %)) 0) 48 | ; ;; thread 2: 2.23606797749979 49 | ; ;; thread 1: 2.23606797749979 50 | ; ;; thread 0: 2.23606797749979 51 | ; ) 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # core.typed.checker.jvm 2 | 3 | 4 | 5 | Type checker for Typed Clojure, for JVM Clojure. 6 | 7 | ## DEPRECATION NOTICE 8 | 9 | This repository is DEPRECATED and development has been moved 10 | to the [core.typed](https://github.com/clojure/core.typed) monorepo. 11 | Please follow [these](https://github.com/clojure/core.typed/blob/master/UPGRADING.md#upgrading-from-07x-to-monorepo) 12 | instructions to upgrade. 13 | 14 | ## Releases and Dependency Information 15 | 16 | Latest stable release is 0.7.1. 17 | 18 | * [All Released Versions](https://search.maven.org/search?q=g:org.clojure%20AND%20a:core.typed.checker.jvm) 19 | 20 | [deps.edn](https://clojure.org/reference/deps_and_cli) dependency information: 21 | 22 | ```clj 23 | org.clojure/core.typed.checker.jvm {:mvn/version "0.7.1"} 24 | ``` 25 | 26 | [Leiningen](https://github.com/technomancy/leiningen) dependency information: 27 | 28 | ```clojure 29 | [org.clojure/core.typed.checker.jvm "0.7.1"] 30 | ``` 31 | 32 | [Maven](https://maven.apache.org/) dependency information: 33 | 34 | ```XML 35 | 36 | org.clojure 37 | core.typed.checker.jvm 38 | 0.7.1 39 | 40 | ``` 41 | 42 | ## YourKit 43 | 44 | YourKit is kindly supporting core.typed and other open source projects with its full-featured Java Profiler. 45 | YourKit, LLC is the creator of innovative and intelligent tools for profiling 46 | Java and .NET applications. Take a look at YourKit's leading software products: 47 | 48 | * YourKit Java Profiler and 49 | * YourKit .NET Profiler. 50 | 51 | ## License 52 | 53 | Copyright © Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 54 | 55 | Licensed under the EPL (see the file epl-v10.html). 56 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/extend_record.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.extend-record 2 | (:require [clojure.core.typed :as t :refer [ann-protocol ann-record]] 3 | #_[clojure.core.typed.checker.jvm.subtype :as sub] 4 | #_[clojure.core.typed.checker.jvm.parse-unparse :as prs] 5 | #_[clojure.core.typed.current-impl :as impl])) 6 | 7 | (t/defprotocol PMaths 8 | (mult-by-two [this] :- PMaths)) 9 | 10 | (t/defprotocol PMathsExtend 11 | (mult-extended [this] :- PMathsExtend)) 12 | 13 | (ann-record SpecialNumber [x :- Number]) 14 | (defrecord SpecialNumber [x] 15 | PMaths 16 | (mult-by-two [this] 17 | (t/ann-form this SpecialNumber) 18 | (assoc this :x (* (:x this) 2)))) 19 | 20 | (extend-protocol PMaths 21 | nil 22 | (mult-by-two [this] 23 | (t/ann-form this nil)) 24 | String 25 | (mult-by-two [this] 26 | (t/ann-form this String))) 27 | 28 | (extend-protocol PMathsExtend 29 | SpecialNumber 30 | (mult-extended [this] 31 | (t/ann-form this SpecialNumber) 32 | (assoc this :x (* (:x this) 2)) 33 | this)) 34 | 35 | ;(not (sub/sub-clj? PMaths SpecialNumber)) 36 | ;(sub/sub-clj? SpecialNumber PMaths) 37 | ;(sub/sub-clj? String PMaths) 38 | ;(sub/sub-clj? SpecialNumber (t/Map Any Any)) 39 | 40 | ;(ancestors SpecialNumber) 41 | ;(prs/parse-clj 'PMaths) 42 | ;(impl/with-clojure-impl 43 | ; (clojure.core.typed.checker.datatype-ancestor-env/get-datatype-ancestors (prs/parse-clj 'SpecialNumber))) 44 | 45 | ;(sub/sub-clj? SpecialNumber PMathsExtend) 46 | ;(not (sub/sub-clj? PMathsExtend SpecialNumber)) 47 | 48 | ;(sub/sub-clj? 49 | ; (HMap :mandatory {:mult-by-two (Fn [Any -> nil])} :complete? true) 50 | ; (U (HMap :mandatory {} :absent-keys #{:mult-by-two}) 51 | ; (HMap :mandatory {:mult-by-two (Fn [Nothing -> String])}))) 52 | ; 53 | ;(sub/sub-clj? 54 | ; [Any -> nil] 55 | ; [Nothing -> Any]) 56 | 57 | ;(sub/sub-clj? String PMaths) 58 | ;(sub/sub-clj? PMaths String) 59 | ;(prs/parse-clj '(I String PMaths)) 60 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/pprint.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.pprint 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest cl-format-test 7 | (is-tc-e #(cl-format nil "abc") 8 | :requires [[clojure.pprint :refer [cl-format]]]) 9 | (is-tc-e #(cl-format nil "abc" 'a :foo "bar") 10 | :requires [[clojure.pprint :refer [cl-format]]]) 11 | (is-tc-e #(cl-format true "abc" 'a :foo "bar") 12 | :requires [[clojure.pprint :refer [cl-format]]]) 13 | (is-tc-e #(let [so System/out 14 | _ (assert so) 15 | o (java.io.OutputStreamWriter. so)] 16 | (assert o) 17 | (cl-format (java.io.BufferedWriter. o) "abc")) 18 | :requires [[clojure.pprint :refer [cl-format]]]) 19 | (is-tc-err #(cl-format "abc" "abc") 20 | :requires [[clojure.pprint :refer [cl-format]]]) 21 | (is-tc-err #(cl-format true true) 22 | :requires [[clojure.pprint :refer [cl-format]]])) 23 | 24 | (deftest fresh-line-test 25 | (is-tc-e #(fresh-line) 26 | :requires [[clojure.pprint :refer [fresh-line]]])) 27 | 28 | (deftest get-pretty-writer-test 29 | (is-tc-e #(let [so System/out 30 | _ (assert so) 31 | o (java.io.OutputStreamWriter. so)] 32 | (assert o) 33 | (get-pretty-writer o)) 34 | [-> java.io.Writer] 35 | :requires [[clojure.pprint :refer [get-pretty-writer]]])) 36 | 37 | (deftest pprint-test 38 | (is-tc-e #(pprint 1) [-> nil] 39 | :requires [[clojure.pprint :refer [pprint]]]) 40 | (is-tc-e #(let [so System/out 41 | _ (assert so) 42 | o (java.io.OutputStreamWriter. so)] 43 | (assert o) 44 | (pprint 1 o)) 45 | [-> nil] 46 | :requires [[clojure.pprint :refer [pprint]]])) 47 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/get.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.get 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.checker.type-ctors :as c] 12 | [clojure.core.typed.checker.type-rep :as r] 13 | [clojure.core.typed.checker.check.invoke-kw :as invoke-kw] 14 | [clojure.core.typed.checker.check.utils :as cu])) 15 | 16 | (defn invoke-get [{:keys [args] :as expr} expected & {:keys [cargs]}] 17 | {:pre [(vector? cargs)] 18 | :post [((some-fn 19 | #(-> % u/expr-type r/TCResult?) 20 | #{cu/not-special}) 21 | %)]} 22 | (assert (#{:invoke :static-call} (:op expr)) (:op expr)) 23 | (assert (vector? cargs)) 24 | (assert (#{2 3} (count args)) "Wrong number of args to clojure.core/get") 25 | (let [[ctarget ckw cdefault] cargs 26 | kwr (u/expr-type ckw)] 27 | (cond 28 | (c/keyword-value? (r/ret-t kwr)) 29 | (assoc expr 30 | :args cargs 31 | u/expr-type (invoke-kw/invoke-keyword 32 | expr 33 | kwr 34 | (u/expr-type ctarget) 35 | (when cdefault 36 | (u/expr-type cdefault)) 37 | expected)) 38 | 39 | ; ((every-pred r/Value? (comp integer? :val)) (ret-t kwr)) 40 | ; (err/nyi-error (str "get lookup of vector (like nth) NYI")) 41 | 42 | :else cu/not-special))) 43 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/set.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.set 10 | (:require [clojure.core.typed.checker.type-ctors :as c] 11 | [clojure.core.typed.current-impl :as impl] 12 | [clojure.core.typed.util-vars :as vs] 13 | [clojure.core.typed.checker.check-below :as below] 14 | [clojure.core.typed.checker.filter-ops :as fo] 15 | [clojure.core.typed.checker.type-rep :as r] 16 | [clojure.core.typed.checker.utils :as u] 17 | [clojure.core.typed.checker.jvm.subtype :as sub] 18 | [clojure.core.typed.checker.check.utils :as cu]) 19 | (:import (clojure.lang PersistentHashSet))) 20 | 21 | (defn check-set [check {:keys [items] :as expr} expected] 22 | {:post [(-> % u/expr-type r/TCResult?) 23 | (vector? (:items %))]} 24 | (let [cargs (mapv check items) 25 | ts (map (comp c/fully-resolve-type r/ret-t u/expr-type) cargs) 26 | res-type (if (every? r/Value? ts) 27 | (r/-hset (r/sorted-type-set ts)) 28 | (impl/impl-case 29 | :clojure (c/RClass-of PersistentHashSet [(apply c/Un ts)]) 30 | :cljs (c/Protocol-of 'cljs.core/ISet [(apply c/Un ts)])))] 31 | (assoc expr 32 | :items cargs 33 | u/expr-type (binding [vs/*current-expr* expr] 34 | (below/maybe-check-below 35 | (r/ret res-type (fo/-true-filter)) 36 | expected))))) 37 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/remove.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.remove 10 | (:require [clojure.core.typed.checker.type-ctors :as c] 11 | [clojure.core.typed.checker.jvm.subtype :as sub] 12 | [clojure.core.typed.checker.type-rep :as r])) 13 | 14 | ;; also not yet correct 15 | ;; produces old without the contents of rem 16 | ;[Type Type -> Type] 17 | (defn remove* [old rem] 18 | (let [old (c/fully-resolve-type old) 19 | rem (c/fully-resolve-type rem) 20 | initial (if (sub/subtype? old rem) 21 | (c/Un) ;the empty type 22 | (cond 23 | ;FIXME TR also tests for App? here. ie (or (r/Name? old) (App? old)) 24 | (r/Name? old) ;; must be different, since they're not subtypes 25 | ;; and n must refer to a distinct struct type 26 | old 27 | (r/Union? old) (let [l (:types old)] 28 | (apply c/Un (map (fn [e] (remove* e rem)) l))) 29 | (r/Mu? old) (remove* (c/unfold old) rem) 30 | (r/Poly? old) (let [vs (c/Poly-fresh-symbols* old) 31 | b (c/Poly-body* vs old)] 32 | (c/Poly* vs 33 | (c/Poly-bbnds* vs old) 34 | (remove* b rem))) 35 | :else old))] 36 | (if (sub/subtype? old initial) old initial))) 37 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/local_result.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.local-result 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.checker.lex-env :as lex] 12 | [clojure.core.typed.errors :as err] 13 | [clojure.core.typed.checker.type-rep :as r] 14 | [clojure.core.typed.util-vars :as vs] 15 | [clojure.core.typed.checker.jvm.parse-unparse :as prs] 16 | [clojure.core.typed.checker.check-below :as below] 17 | [clojure.core.typed.checker.type-ctors :as c] 18 | [clojure.core.typed.checker.filter-ops :as fo] 19 | [clojure.core.typed.checker.check.utils :as cu])) 20 | 21 | (defn local-ret [sym] 22 | {:pre [(symbol? sym)] 23 | :post [(r/TCResult? %)]} 24 | (let [[obj t] ((juxt lex/lookup-alias lex/lookup-local) sym)] 25 | (when-not t 26 | (err/int-error (str "Could not find type for local variable " sym))) 27 | (r/ret t 28 | (if (c/overlap t (c/Un r/-nil r/-false)) 29 | (fo/-FS (fo/-not-filter-at r/-falsy obj) 30 | (fo/-filter-at r/-falsy obj)) 31 | (fo/-true-filter)) 32 | obj))) 33 | 34 | (defn local-result [expr sym expected] 35 | {:pre [(con/local-sym? sym) 36 | ((some-fn nil? r/TCResult?) expected)] 37 | :post [(r/TCResult? %)]} 38 | (binding [vs/*current-expr* expr] 39 | (prs/with-unparse-ns (cu/expr-ns expr) 40 | (below/maybe-check-below 41 | (local-ret sym) 42 | expected)))) 43 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/const.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.const 10 | (:require [clojure.core.typed.checker.object-rep :as obj] 11 | [clojure.core.typed.checker.lex-env :as lex] 12 | [clojure.core.typed.checker.utils :as u] 13 | [clojure.core.typed.checker.filter-rep :as fl] 14 | [clojure.core.typed.checker.filter-ops :as fo] 15 | [clojure.core.typed.checker.check-below :as below] 16 | [clojure.core.typed.checker.type-rep :as r])) 17 | 18 | (defn flow-for-value [] 19 | (let [props (:props (lex/lexical-env)) 20 | flow (r/-flow (apply fo/-and fl/-top props))] 21 | flow)) 22 | 23 | (defn filter-for-value [val] 24 | (if val 25 | (fo/-FS fl/-top fl/-bot) 26 | (fo/-FS fl/-bot fl/-top))) 27 | 28 | (defn check-const 29 | "Given a :const node and an expected type returns a new :const 30 | node annotated with its type. 31 | 32 | quoted? should be true if this :const node is nested inside a 33 | :quote node, otherwise should be false" 34 | [constant-type quoted? {:keys [val] :as expr} expected] 35 | {:pre [(#{:const} (:op expr)) 36 | ((some-fn nil? r/TCResult?) expected)] 37 | :post [(-> % u/expr-type r/TCResult?)]} 38 | (let [inferred-ret (r/ret (constant-type val quoted?) 39 | (filter-for-value val) 40 | obj/-empty 41 | (flow-for-value))] 42 | (assoc expr 43 | u/expr-type (below/maybe-check-below inferred-ret expected)))) 44 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/declared_kind_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.declared-kind-env 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.errors :as err] 12 | [clojure.core.typed.checker.type-rep :as r] 13 | [clojure.core.typed.env :as env])) 14 | 15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16 | ;; Declared kind Env 17 | 18 | (def declared-kind-env? (con/hash-c? symbol? r/TypeFn?)) 19 | 20 | (def current-declared-kinds-kw ::current-declared-kinds) 21 | 22 | (defn declared-kinds [] 23 | {:post [(map? %)]} 24 | (get (env/deref-checker) current-declared-kinds-kw {})) 25 | 26 | (defn reset-declared-kinds! [m] 27 | {:pre [(declared-kind-env? m)] 28 | :post [(nil? %)]} 29 | (env/swap-checker! assoc current-declared-kinds-kw m) 30 | nil) 31 | 32 | (defn add-declared-kind [sym tfn] 33 | {:pre [(symbol? sym) 34 | (r/TypeFn? tfn)] 35 | :post [(nil? %)]} 36 | (env/swap-checker! assoc-in [current-declared-kinds-kw sym] tfn) 37 | nil) 38 | 39 | (defn declared-kind-or-nil [sym] 40 | (get (declared-kinds) sym)) 41 | 42 | (defn get-declared-kind [sym] 43 | (if-let [tfn (declared-kind-or-nil sym)] 44 | tfn 45 | (err/int-error (str "No declared kind for Name " sym)))) 46 | 47 | (defn has-declared-kind? [sym] 48 | (boolean (declared-kind-or-nil sym))) 49 | 50 | (defn remove-declared-kind [sym] 51 | (env/swap-checker! update current-declared-kinds-kw dissoc sym) 52 | nil) 53 | 54 | (defn declare-alias-kind* [sym ty] 55 | (add-declared-kind sym ty)) 56 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/inspector.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.inspector 2 | (:require [clojure.core.typed :as t] 3 | [clojure.test :refer :all] 4 | [clojure.core.typed.test.test-utils :refer :all])) 5 | 6 | (deftest atom?-test 7 | (is-tc-e #(atom? "abc") [-> Boolean] 8 | :requires [[clojure.inspector :refer [atom?]]]) 9 | (is-tc-err #(atom? "abc") [-> String] 10 | :requires [[clojure.inspector :refer [atom?]]])) 11 | 12 | (deftest collection-tag-test 13 | (is-tc-e #(collection-tag "abc") [-> Keyword] 14 | :requires [[clojure.inspector :refer [collection-tag]]]) 15 | (is-tc-err #(collection-tag "abc") [-> String] 16 | :requires [[clojure.inspector :refer [collection-tag]]])) 17 | 18 | (deftest tree-model-test 19 | (is-tc-e #(tree-model "abc") 20 | :requires [[clojure.inspector :refer [tree-model]]])) 21 | 22 | (deftest old-table-model-test 23 | (is-tc-e #(old-table-model [[1 2 3] [4 5 6] [7 8 9] [10 11 12]]) 24 | :requires [[clojure.inspector :refer [old-table-model]]]) 25 | (is-tc-err #(old-table-model 1) 26 | :requires [[clojure.inspector :refer [old-table-model]]])) 27 | 28 | (deftest inspect-test 29 | (is-tc-e #(inspect "abc") [-> javax.swing.JFrame] 30 | :requires [[clojure.inspector :refer [inspect]]]) 31 | (is-tc-err #(inspect "abc") [-> String] 32 | :requires [[clojure.inspector :refer [inspect]]])) 33 | 34 | (deftest inspect-tree-test 35 | (is-tc-e #(inspect-tree "abc") [-> javax.swing.JFrame] 36 | :requires [[clojure.inspector :refer [inspect-tree]]]) 37 | (is-tc-err #(inspect-tree "abc") [-> String] 38 | :requires [[clojure.inspector :refer [inspect-tree]]])) 39 | 40 | (deftest inspect-table-test 41 | (is-tc-e #(inspect-table [[1 2 3] [4 5 6] [7 8 9] [10 11 12]]) [-> javax.swing.JFrame] 42 | :requires [[clojure.inspector :refer [inspect-table]]]) 43 | (is-tc-err #(inspect-table 1) 44 | :requires [[clojure.inspector :refer [inspect-table]]])) 45 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/print_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.print-env 10 | (:require [clojure.core.typed.checker.lex-env :as lex] 11 | [clojure.core.typed.checker.tvar-env :as tvar-env] 12 | [clojure.core.typed.checker.tvar-bnds :as tvar-bnds] 13 | [clojure.core.typed.checker.jvm.parse-unparse :as prs])) 14 | 15 | (defn print-env* 16 | ([] (print-env* (lex/lexical-env))) 17 | ([e] 18 | {:pre [(lex/PropEnv? e)]} 19 | ;; DO NOT REMOVE 20 | (let [tvar-scope tvar-env/*current-tvars* 21 | tvar-bounds tvar-bnds/*current-tvar-bnds* 22 | scoped-names (keys tvar-scope) 23 | actual-names (map :name (vals tvar-scope)) 24 | _ (every? symbol? actual-names) 25 | actual-bnds (map tvar-bounds actual-names)] 26 | (prn {:env (into {} (for [[k v] (:l e)] 27 | [k (prs/unparse-type v)])) 28 | :props (map prs/unparse-filter (:props e)) 29 | :aliases (:aliases e) 30 | ;:frees (map (t/fn 31 | ; [nme :- t/Sym, bnd :- (U nil Bounds)] 32 | ; {:pre [(symbol? nme) 33 | ; ((some-fn nil? r/Bounds?) bnd)]} 34 | ; (if bnd 35 | ; (prs/unparse-poly-bounds-entry nme bnd) 36 | ; [nme 'NO-BOUNDS])) 37 | ; scoped-names 38 | ; actual-bnds) 39 | ;:tvar-scope tvar-scope 40 | ;:tvar-bnds tvar-bounds 41 | })))) 42 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src/main/clojure"], 2 | :deps 3 | {org.clojure/clojure {:mvn/version "1.9.0"}, 4 | org.clojure/core.typed.analyzer.jvm {:mvn/version "0.7.1"}, 5 | org.typedclojure/core.typed.lib.clojure 6 | {:mvn/version "0.7.0"}, 7 | org.clojure/tools.namespace {:mvn/version "0.3.0-alpha4"}, 8 | org.clojure/core.typed.runtime.jvm {:git/url "https://github.com/clojure/core.typed.runtime.jvm.git" 9 | :sha "859cb09c2054060c89fef6b46185f18e14cc1134"}, 10 | org.clojure/math.combinatorics 11 | {:mvn/version "0.1.4", :exclusions [org.clojure/clojure]}, 12 | org.clojure/tools.reader {:mvn/version "1.1.1"}, 13 | org.typedclojure/core.typed.lang.jvm {:mvn/version "0.7.0"}, 14 | org.clojure/core.cache {:mvn/version "0.8.2"}}, 15 | :mvn/repos 16 | {"sonatype-oss-public" 17 | {:url "https://oss.sonatype.org/content/groups/public/"}}, 18 | :aliases 19 | {:script {:extra-paths ["script"]}, 20 | :nREPL 21 | {:extra-deps 22 | {nrepl/nrepl {:mvn/version "0.6.0"} 23 | cider/cider-nrepl {:mvn/version "0.22.4"}}, 24 | :main-opts ["-m" "nrepl.cmdline" "--interactive" 25 | #_" 26 | Note: 27 | introducing other middleware makes vim-fireplace choose 28 | fipp for pprint, which doesn't play well with the delicately 29 | defined classes in type-rep." 30 | "--middleware" "[cider.nrepl/wrap-complete]" 31 | ]}, 32 | :test 33 | {:extra-paths ["src/test/clojure" "src/test/resources"], 34 | :extra-deps 35 | {org.clojure/tools.nrepl 36 | {:mvn/version "0.2.6", :exclusions [org.clojure/clojure]}, 37 | org.clojure/core.async 38 | {:mvn/version "0.3.465", 39 | :exclusions [org.clojure/tools.analyzer.jvm]}}}, 40 | :runner 41 | {:extra-deps 42 | {org.typedclojure/test-runner 43 | {:git/url "https://github.com/typedclojure/test-runner", 44 | :sha "2d7af465ac90b2d083753daf251bdb4a09ae97cd"}}, 45 | :main-opts 46 | ["-m" 47 | "cognitect.test-runner" 48 | "-d" 49 | "src/test/clojure/clojure/core/typed/test" 50 | "-r" 51 | ".*"]}}} 52 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/letfn_runtime.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.letfn-runtime 2 | (:use clojure.test) 3 | (:require [clojure.core.typed :as t])) 4 | 5 | #_(deftest letfn-syntax-test 6 | (is (= 7 | (letfn [(a [b] b)] 8 | (a 1)) 9 | (t/letfn 10 | [(a [b] b)] 11 | (a 1)) 12 | (t/letfn :- Any 13 | [(a [b] b)] 14 | (a 1)) 15 | (t/letfn :- Any 16 | [(a [b :- Bar] :- Any b)] 17 | (a 1)) 18 | (t/letfn 19 | [(a [b :- Bar] b)] 20 | (a 1)) 21 | (t/letfn 22 | [(a ([b :- Bar] :- Any b))] 23 | (a 1)) 24 | (t/letfn 25 | [(a ([b :- Bar] :- Any b))] 26 | (a 1)) 27 | (t/letfn 28 | [(a ([b :- Bar] b))] 29 | (a 1)) 30 | (t/letfn 31 | [(a [b :- Bar] b)] 32 | (a 1)) 33 | (t/letfn 34 | [a :- [Any -> Bar] 35 | (a [b] b)] 36 | (a 1)) 37 | (t/letfn 38 | [a :- [Any -> Bar] 39 | (a [b :- Bar] :- Any b)] 40 | (a 1)) 41 | ))) 42 | 43 | #_(deftest def-syntax-test 44 | (is (= @(def a 1) 45 | @(t/def a 1) 46 | @(t/def a "docstring" 1) 47 | @(t/def a "docstring" :- Foo 1) 48 | @(t/def :- Foo a 1)))) 49 | 50 | #_(deftest defn-syntax-test 51 | ; this unit test is useless atm 52 | (is (= (defn a [b] b) 53 | (t/defn a [b] b) 54 | (t/defn a "docstring" [b] b) 55 | (t/defn a [b :- Any] b) 56 | (t/defn a [b :- Any] :- Any b) 57 | (t/defn a "docstring" [b :- Any] :- Any b) 58 | (t/defn a "docstring" [b :- Any] :- Any {:pre []} b) 59 | (t/defn a "docstring" {:attr-map nil} [b :- Any] :- Any {:pre []} b) 60 | (t/defn a ([b :- Any] b)) 61 | (t/defn a ([b :- Any] :- Any b)) 62 | (t/defn a "docstring" ([b :- Any] :- Any b)) 63 | (t/defn a "docstring" {:attr-map nil} ([b :- Any] :- Any b))))) 64 | 65 | #_(deftest do-syntax-test 66 | (is (= (do 1 2) 67 | (t/do 1 2) 68 | (t/do :- Any 1 2)))) 69 | 70 | #_(deftest let-syntax-test 71 | (is (= (let [a 1] a)))) 72 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/destructure.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.destructure 2 | (:import (clojure.lang APersistentVector APersistentMap)) 3 | (:require [clojure.core.typed :as t :refer [ann-form check-ns cf]])) 4 | 5 | ;; map destructuring 6 | (let [{:keys [b] :or {b 3}} {}] 7 | (ann-form b Number)) 8 | 9 | (let* [map__65083 {} 10 | map__65083 (if (seq? map__65083) 11 | (clojure.lang.PersistentHashMap/create (clojure.core/seq map__65083)) 12 | map__65083) 13 | b (get map__65083 :b 3)] 14 | (ann-form b Number)) 15 | 16 | (let [{:as c} {}] 17 | (ann-form c '{})) 18 | 19 | (let [{:as c} nil] 20 | (ann-form c nil)) 21 | 22 | ;FIXME 23 | ;(let [{:strs [str] :syms [symb]} (ann-form {} (Extends [(APersistentMap Any String)] :without [(clojure.lang.ISeq Any)]))] 24 | ; (ann-form symb (U nil String)) 25 | ; (ann-form str (U nil String))) 26 | 27 | ;; vector destructuring 28 | (let [[a b & c :as d] (ann-form [] (APersistentVector Number))] 29 | (ann-form a (t/U nil Number)) 30 | (ann-form b (t/U nil Number)) 31 | (ann-form c (t/U nil (t/Seqable Number))) 32 | (ann-form d (t/U nil (APersistentVector Number)))) 33 | 34 | (let [[[x1 y1] 35 | [x2 y2]] [[1 2] [3 4]]] 36 | (ann-form [x1 y1 x2 y2] 37 | (t/Seqable Number))) 38 | 39 | (let [[a b & c :as str] "asdjhhfdas"] 40 | ;could do a bit better there 41 | (ann-form [a b] (t/Seqable (t/U nil Character))) 42 | (ann-form c (t/U nil (t/Seqable Character))) 43 | (ann-form str String)) 44 | 45 | ;vectors 46 | (let [[a b c & d :as e] [1 2 3 4 5 6 7]] 47 | (ann-form a Number) 48 | (ann-form b Number) 49 | (ann-form c Number) 50 | (ann-form [a b c] (t/Seqable Number)) 51 | (ann-form d (t/U nil (t/Seqable Number))) 52 | (ann-form e (t/Seqable Number))) 53 | 54 | ;lists 55 | (let [[a b c & d :as e] '(1 2 3 4 5 6 7)] 56 | ; FIXME stopped working with 1.9.0 57 | ; to fix, start adding HList to `AnySequential?` predicate 58 | ;(ann-form [a b c] (t/Seqable Number)) 59 | (ann-form d (t/U nil (t/Seqable Number))) 60 | (ann-form e (t/Seqable Number))) 61 | 62 | ;flexible map destructing 63 | (let [{:keys [a]} (ann-form '() (t/U nil (t/Seq t/Any)))] 64 | a) 65 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/namespaced_specials.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.namespaced-specials 2 | (:require [clojure.core.typed.test.test-utils :refer :all] 3 | [clojure.test :refer :all])) 4 | 5 | ;backwards compatibility tests for type syntax 6 | 7 | (deftest value-test 8 | (is-tc-e (ann-form :a ':a)) 9 | ;old syntax 10 | (is-cf (clojure.core.typed/ann-form :a (Value :a))) 11 | (is-tc-e (ann-form :a (Value :a))) 12 | (is-tc-e (ann-form :a (t/Value :a))) 13 | ; runtime parsing 14 | (is-tc-e (defalias Foo (t/Value :a))) 15 | (is-tc-e (defalias Foo (Value :a))) 16 | ; old syntax 17 | (is-cf (clojure.core.typed/defalias Foo (Value :a)))) 18 | 19 | (deftest quote-test 20 | ; bare quote should always resolve to clojure.core/quote 21 | (is-tc-e (do (defalias quote Any) 22 | (defalias TAlias (quote :a)) 23 | (ann-form :a TAlias))) 24 | (is-tc-e (do (defalias quote Any) 25 | (defalias TAlias (quote {:a Num})) 26 | (ann-form {:a 1} TAlias)))) 27 | 28 | (deftest hmap-test 29 | (is-tc-e (ann-form {:a 1} (HMap :mandatory {:a Num}))) 30 | ;old syntax 31 | (is-cf (clojure.core.typed/ann-form {:a 1} (HMap :mandatory {:a clojure.core.typed/Num}))) 32 | ;new syntax 33 | (is-tc-e (ann-form {:a 1} (t/HMap :mandatory {:a Num})))) 34 | 35 | (deftest hvec-test 36 | (is-tc-e (ann-form [1] (HVec [Num]))) 37 | ;old syntax 38 | (is-cf (clojure.core.typed/ann-form 39 | [1] 40 | (HVec [clojure.core.typed/Num]))) 41 | ;new syntax 42 | (is-tc-e (ann-form 43 | [1] 44 | (t/HVec [Num])))) 45 | 46 | (deftest Any-test 47 | (is-tc-e (ann-form {:a 1} Any)) 48 | ;old syntax 49 | (is-cf (clojure.core.typed/ann-form {:a 1} Any)) 50 | ; new syntax 51 | (is-tc-e (ann-form {:a 1} t/Any))) 52 | 53 | (deftest Nothing-test 54 | (is-tc-e (ann-form (fn [] (throw (Exception.))) 55 | [-> Nothing])) 56 | ;old syntax 57 | (is-cf (clojure.core.typed/ann-form 58 | (fn [] (throw (Exception.))) 59 | [-> Nothing])) 60 | ; new syntax 61 | (is-tc-e (ann-form 62 | (fn [] (throw (Exception.))) 63 | [-> t/Nothing]))) 64 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/case.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.case 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.checker.utils :as u] 12 | [clojure.core.typed.util-vars :as vs] 13 | [clojure.core.typed.contract-utils :as con] 14 | [clojure.core.typed.checker.var-env :as var-env] 15 | [clojure.core.typed.checker.lex-env :as lex] 16 | [clojure.core.typed.checker.update :as update] 17 | [clojure.core.typed.checker.jvm.tc-equiv :as equiv])) 18 | 19 | (defn check-case-thens [check-fn target-ret tst-rets case-thens expected] 20 | {:pre [(r/TCResult? target-ret) 21 | (every? r/TCResult? tst-rets) 22 | (== (count tst-rets) 23 | (count case-thens))] 24 | :post [((every-pred vector? 25 | (con/every-c? (comp #{:case-then} :op))) 26 | %)]} 27 | (letfn [(check-case-then [tst-ret {:keys [then] :as case-then}] 28 | (let [{{fs+ :then} :fl :as rslt} (equiv/tc-equiv := [target-ret tst-ret] nil) 29 | flag+ (atom true) 30 | env-thn (update/env+ (lex/lexical-env) [fs+] flag+) 31 | _ (when-not @flag+ 32 | ;; FIXME should we ignore this branch? 33 | (u/tc-warning "Local became bottom when checking case then")) 34 | cthen (var-env/with-lexical-env env-thn 35 | (check-fn then expected))] 36 | (assoc case-then 37 | :then cthen 38 | u/expr-type (u/expr-type cthen))))] 39 | (mapv check-case-then 40 | tst-rets 41 | case-thens))) 42 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/reset_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.reset-env 10 | (:require [clojure.core.typed.checker.jvm.base-env :as bse-clj] 11 | [clojure.core.typed.checker.ns-options :as ns-opts] 12 | [clojure.core.typed.current-impl :as impl] 13 | [clojure.core.typed.checker.jvm.mm-env :as mmenv])) 14 | 15 | (def ^:private reset-cljs-envs! (delay (impl/dynaload 'clojure.core.typed.checker.jvm.base-env-cljs/reset-cljs-envs!))) 16 | 17 | (defn reset-envs! 18 | "Reset all environments for all implementations. Cannot be called 19 | if a specific implementation is currently bound" 20 | ([] (reset-envs! false)) 21 | ([cljs?] 22 | (let [] 23 | (impl/impl-case 24 | :clojure 25 | (do (bse-clj/reset-clojure-envs!) 26 | (mmenv/reset-mm-dispatch-env!) 27 | (ns-opts/reset-ns-opts!)) 28 | :cljs 29 | (do 30 | (assert cljs? "No ClojureScript dependency") 31 | (when cljs? 32 | (@reset-cljs-envs!) 33 | (ns-opts/reset-ns-opts!)))) 34 | nil))) 35 | 36 | (defn load-core-envs! 37 | "Add core annotations to environments for all implementations. Cannot be called 38 | if a specific implementation is currently bound" 39 | ([] (load-core-envs! false)) 40 | ([cljs?] 41 | (let [] 42 | (impl/impl-case 43 | :clojure 44 | (do (bse-clj/refresh-core-clojure-envs!) 45 | ;(mmenv/reset-mm-dispatch-env!) 46 | ;(ns-opts/reset-ns-opts!) 47 | ) 48 | :cljs 49 | (do 50 | (assert nil "load-core-envs! TODO CLJS") 51 | (assert cljs? "No ClojureScript dependency") 52 | (when cljs? 53 | (@reset-cljs-envs!) 54 | (ns-opts/reset-ns-opts!)))) 55 | nil))) 56 | 57 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/fold_rep.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.fold-rep) 10 | 11 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 12 | ;; Type Folding 13 | 14 | (def fold-rhs-default ::fold-rhs) 15 | 16 | (defn derive-default [& kws] 17 | (doseq [kw kws] 18 | (derive kw fold-rhs-default))) 19 | 20 | ;1. fold-rhs calls sends 21 | ; a. Type to type-rec 22 | ; b. Filter to filter-rec 23 | ; c. Object to object-rec 24 | 25 | ;visit a type nested inside ty. Add methods with a mode deriving ::visit-type-default 26 | (defmulti fold-rhs (fn [mode options ty] 27 | [mode (class ty)])) 28 | 29 | ; fld-fn has type-rec, filter-rec and object-rec in scope 30 | (defmacro add-fold-case [mode ty fld-fn] 31 | `(defmethod fold-rhs [~mode ~ty] 32 | ~(symbol (str "fold-rhs " (name mode) ty)) 33 | [mode# options# ty#] 34 | (let [~'[type-rec filter-rec object-rec pathelem-rec] 35 | (map #(or (% options#) 36 | (partial fold-rhs mode# options#)) 37 | [:type-rec :filter-rec :object-rec :pathelem-rec])] 38 | (~fld-fn ty# options#)))) 39 | 40 | (defmacro add-default-fold-case [ty fld-fn] 41 | `(add-fold-case fold-rhs-default ~ty ~fld-fn)) 42 | 43 | (defn sub-pe [st mode] 44 | #(fold-rhs fold-rhs-default 45 | {:type-rec st 46 | :pathelem-rec (sub-pe st mode)} 47 | %)) 48 | 49 | (defn sub-f [st mode] 50 | #(fold-rhs mode 51 | {:type-rec st 52 | :filter-rec (sub-f st mode) 53 | :pathelem-rec (sub-pe st mode)} 54 | %)) 55 | 56 | (defn sub-o [st mode] 57 | #(fold-rhs mode 58 | {:type-rec st 59 | :object-rec (sub-o st mode) 60 | :pathelem-rec (sub-pe st mode)} 61 | %)) 62 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/rbt_types.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.rbt-types 2 | (:require [clojure.core.typed :as t :refer [defalias declare-names]])) 3 | 4 | ;------------------------------- 5 | ; 'Normal' types 6 | ;------------------------------- 7 | 8 | (defalias EntryT 9 | "The payload" 10 | '{:key Number 11 | :datum Number}) 12 | 13 | (defalias Empty 14 | "A terminating node." 15 | '{:tree ':Empty}) 16 | 17 | (defalias Red 18 | "A red node" 19 | (t/TFn [[l :variance :covariant] 20 | [r :variance :covariant]] 21 | '{:tree ':Red 22 | :entry EntryT 23 | :left l 24 | :right r})) 25 | 26 | (defalias Black 27 | "A black node" 28 | (t/TFn [[l :variance :covariant] 29 | [r :variance :covariant]] 30 | '{:tree ':Black 31 | :entry EntryT 32 | :left l 33 | :right r})) 34 | 35 | 36 | ;------------------------------- 37 | ; 'Refinement' types 38 | ;------------------------------- 39 | 40 | (defalias rbt 41 | "Trees with only black children for red nodes" 42 | (t/Rec [rbt] 43 | (t/U 44 | Empty 45 | (Black rbt rbt) 46 | ;(Red bt bt) 47 | (Red (t/U 48 | Empty 49 | (Black rbt rbt)) 50 | (t/U 51 | Empty 52 | (Black rbt rbt)))))) 53 | 54 | (defalias bt 55 | "Like rbt but additionally the root node is black" 56 | (t/Rec [bt] 57 | (t/U 58 | Empty 59 | ;(Black rbt rbt) 60 | (Black 61 | (t/U 62 | Empty 63 | (Black rbt rbt) 64 | (Red bt bt)) 65 | (t/U 66 | Empty 67 | (Black rbt rbt) 68 | (Red bt bt)))))) 69 | 70 | (defalias red 71 | "Trees with a red root" 72 | (Red bt bt)) 73 | 74 | (defalias badRoot 75 | "Invariant possibly violated at the root" 76 | (t/U 77 | Empty 78 | (Black rbt bt) 79 | (Red rbt bt) 80 | (Red bt rbt))) 81 | 82 | (defalias badLeft 83 | "Invariant possibly violated at the left child" 84 | (t/U 85 | Empty 86 | (Black rbt rbt) 87 | (Red bt bt) 88 | (Black badRoot rbt))) 89 | 90 | (defalias badRight 91 | "Invariant possibly violated at the right child" 92 | (t/U 93 | Empty 94 | (Black rbt rbt) 95 | (Red bt bt) 96 | (Black rbt badRoot))) 97 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/init.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.init 10 | (:require [clojure.core.typed.current-impl :as impl])) 11 | 12 | (defonce ^:private attempted-loading? (atom false)) 13 | (defonce ^:private successfully-loaded? (atom false)) 14 | (defonce ^:private cljs-loaded? (atom false)) 15 | 16 | (defonce ^:private cljs-present? (atom false)) 17 | 18 | (defn loaded? [] 19 | @successfully-loaded?) 20 | 21 | (defn has-cljs-loaded? [] 22 | @cljs-loaded?) 23 | 24 | (defn load-impl 25 | ([] (load-impl false)) 26 | ([cljs?] 27 | (cond 28 | (and @attempted-loading? 29 | (not @successfully-loaded?)) 30 | (throw (Exception. 31 | (str "There was previously an unrecoverable internal error while loading core.typed." 32 | " Please restart your process."))) 33 | 34 | (and @successfully-loaded? @attempted-loading? 35 | (if cljs? 36 | @cljs-loaded? 37 | true)) 38 | nil 39 | 40 | :else 41 | (do 42 | (try 43 | (reset! attempted-loading? true) 44 | (catch Exception e 45 | (reset! successfully-loaded? false) 46 | (throw e))) 47 | (reset! successfully-loaded? true) 48 | (println "Building core.typed base environments ...") 49 | (flush) 50 | ;(impl/with-clojure-impl 51 | ; ((impl/dynaload 'clojure.core.typed.checker.reset-env/reset-envs!))) 52 | (impl/register!) 53 | (impl/with-clojure-impl 54 | ((impl/dynaload 'clojure.core.typed.checker.reset-env/load-core-envs!))) 55 | (when cljs? 56 | (impl/with-cljs-impl 57 | ;; FIXME should be load-core-envs! 58 | ((impl/dynaload 'clojure.core.typed.checker.reset-env/reset-envs!) cljs?))) 59 | (println "Finished building base environments") 60 | (flush) 61 | nil)))) 62 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/jvm/array_ops.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.jvm.array-ops 10 | (:require [clojure.core.typed.checker.type-rep :as r] 11 | [clojure.core.typed.checker.type-ctors :as c])) 12 | 13 | ;Return a Class that generalises what this Clojure type will look like from Java, 14 | ;suitable for use as a Java primitive array member type. 15 | ; 16 | ; (Type->array-member-Class (parse-type 'nil)) => Object 17 | ; (Type->array-member-Class (parse-type '(U nil Number))) => Number 18 | ; (Type->array-member-Class (parse-type '(Array (U nil Number)))) =~> (Array Number) 19 | 20 | ;(ann Type->array-member-Class (Fn [Type -> (Option Class)] 21 | ; [Type t/Any -> (Option Class)])) 22 | (defn Type->array-member-Class 23 | ([ty] (Type->array-member-Class ty false)) 24 | ([ty nilok?] 25 | {:pre [(r/Type? ty)]} 26 | (cond 27 | (c/requires-resolving? ty) (Type->array-member-Class (c/-resolve ty) nilok?) 28 | (r/Nil? ty) (if nilok? 29 | nil 30 | Object) 31 | (r/Value? ty) (c/Value->Class ty) 32 | ;; handles most common case of (U nil Type) 33 | (r/Union? ty) (let [clss (map #(Type->array-member-Class % true) (:types ty)) 34 | prim-and-nil? (and (some nil? clss) 35 | (some #(when % (.isPrimitive ^Class %)) clss)) 36 | nonil-clss (remove nil? clss)] 37 | (if (and (= 1 (count nonil-clss)) 38 | (not prim-and-nil?)) 39 | (first nonil-clss) 40 | Object)) 41 | (r/Intersection? ty) Object 42 | (r/RClass? ty) (r/RClass->Class ty) 43 | (r/PrimitiveArray? ty) (class (make-array (Type->array-member-Class (:jtype ty) false) 0)) 44 | :else Object))) 45 | 46 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/async.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.async 2 | (:require 3 | [clojure.core.typed.test.test-utils :refer :all] 4 | [clojure.test :refer :all] 5 | [clojure.core.typed :as t] 6 | [clojure.core.async :as a])) 7 | 8 | ; wrap all these tests in thunks to prevent side effects 9 | 10 | (deftest async-test 11 | (is-tc-e 12 | #(let [c (chan :- t/Str)] 13 | (go (a/>! c "hello")) 14 | (prn (a/!! c1 "hi") 25 | (a/>!! c2 "there")) 26 | :requires [[clojure.core.async :as a] 27 | [clojure.core.typed.async :as ta :refer [go chan]]]) 28 | (is-tc-e 29 | #(a/alts!! [(a/chan) (a/chan)] :priority true) 30 | :requires [[clojure.core.async :as a] 31 | [clojure.core.typed.async]]) 32 | (is-tc-e 33 | (do 34 | (ann lift-chan (All [x y] [[x -> y] -> [(Chan x) -> (Chan y)]])) 35 | (defn lift-chan [function] 36 | (fn [in :- (Chan x)] 37 | (let [out (chan :- y)] 38 | (go 39 | (loop [] 40 | (let [rcv (! out (function rcv)))))) 43 | out))) 44 | 45 | (ann upper-case [Str -> Str]) 46 | (defn upper-case [s] s) 47 | 48 | (ann upcase [(Chan Str) -> (Chan Str)]) 49 | (def upcase (lift-chan upper-case)) 50 | (upcase (chan :- Str))) 51 | :requires [[clojure.core.async :as a :refer [!]] 52 | [clojure.core.typed.async :refer [chan go Chan]]])) 53 | 54 | ;(let [c1 (chan) 55 | ; c2 (chan :- t/Str)] 56 | ; (go (while true 57 | ; (let [[v ch] (a/alts! [c1 c2])] 58 | ; (println "Read" v "from" ch)))) 59 | ; (go (a/>! c1 "hi")) 60 | ; (go (a/>! c2 "there"))) 61 | 62 | (comment 63 | (require '[clojure.core.typed.current-impl :as impl] 64 | '[clojure.core.typed.checker.jvm.analyze-clj :as ana] 65 | '[clojure.core.typed.util-vars :as vs]) 66 | ) 67 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/impl_protocols.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki 10 | clojure.core.typed.checker.impl-protocols 11 | (:refer-clojure :exclude [defrecord defprotocol]) 12 | (:require [clojure.core.typed.checker.def-utils :as u] 13 | [clojure.core.typed :as t])) 14 | 15 | ;; Implementation Protocols and protocol predicates go here. 16 | ;; 17 | 18 | ;; Type protocols 19 | 20 | (t/ann-protocol TCType) 21 | (u/defprotocol TCType) 22 | 23 | (t/ann-protocol TCAnyType) 24 | (u/defprotocol TCAnyType) 25 | 26 | (t/ann-protocol IScope 27 | scope-body 28 | [IScope -> (t/U TCType IScope)]) 29 | (u/defprotocol IScope 30 | (scope-body [this])) 31 | 32 | (t/ann ^:no-check IScope? (t/Pred IScope)) 33 | (defn IScope? [a] 34 | (instance? clojure.core.typed.checker.impl_protocols.IScope a)) 35 | 36 | (t/ann-protocol IMu 37 | mu-scope 38 | [IMu -> IScope]) 39 | (u/defprotocol IMu 40 | (mu-scope [this])) 41 | 42 | ;; Filter protocols 43 | 44 | (t/ann-protocol IFilter) 45 | (u/defprotocol IFilter) 46 | 47 | (t/ann ^:no-check IFilter? (t/Pred IFilter)) 48 | (defn IFilter? [a] 49 | (instance? clojure.core.typed.checker.impl_protocols.IFilter a)) 50 | 51 | (t/ann-protocol IFilterSet 52 | then-filter 53 | [IFilterSet -> IFilter] 54 | else-filter 55 | [IFilterSet -> IFilter]) 56 | (u/defprotocol IFilterSet 57 | (then-filter [this]) 58 | (else-filter [this])) 59 | 60 | (t/ann ^:no-check IFilterSet? (t/Pred IFilterSet)) 61 | (defn IFilterSet? [a] 62 | (instance? clojure.core.typed.checker.impl_protocols.IFilterSet a)) 63 | 64 | ;; Object protocols 65 | 66 | (t/ann-protocol IRObject) 67 | (u/defprotocol IRObject) 68 | 69 | (t/ann ^:no-check IRObject? (t/Pred IRObject)) 70 | (defn IRObject? [a] 71 | (instance? clojure.core.typed.checker.impl_protocols.IRObject a)) 72 | -------------------------------------------------------------------------------- /src/test/clojure/clojure/core/typed/test/core_match.clj: -------------------------------------------------------------------------------- 1 | (ns clojure.core.typed.test.core-match 2 | (:refer-clojure :exclude [macroexpand]) 3 | (:import (clojure.lang Keyword)) 4 | (:require [clojure.core.typed :refer [check-ns ann ann-form typed-deps]] 5 | [clojure.core.typed.hole :refer [noisy-hole]] 6 | ;[clojure.jvm.tools.analyzer.hygienic :refer [macroexpand]] 7 | [clojure.pprint :refer [pprint]])) 8 | (comment 9 | (require '[clojure.core.match :refer [match]]) 10 | 11 | (typed-deps clojure.core.typed.hole) 12 | 13 | (let [x true 14 | y true 15 | z true] 16 | (match [x y z] 17 | [_ false true] 1 18 | [false true _ ] 2 19 | [_ _ false] 3 20 | [_ _ true] 4)) 21 | 22 | (-> 23 | (let [x 1 y 2 z 4] 24 | (match [x y z] 25 | [1 2 b] [:a0 b] 26 | [a 2 4] [:a1 a])) 27 | (ann-form (U nil '[Keyword Number]))) 28 | 29 | (-> 30 | (match [['my-sym]] 31 | [['my-sym]] :success) ;; Branch is chosen because (= 'my-sym 'my-sym) 32 | (ann-form (U nil ':success))) 33 | 34 | (-> 35 | (let [a (+ 1 2)] 36 | (match [[3]] 37 | [[a]] a)) ;; 3 matches against the value of `a`, local binding is preserved 38 | ;; => 3 39 | (ann-form (U nil '3))) 40 | 41 | (-> 42 | (match [['my-sym]] 43 | [[a]] a) ;; a is a wildcard, here bound to 'my-sym on the right of the pattern row 44 | ;; => 'my-sym 45 | (ann-form (U nil 'my-sym))) 46 | 47 | (-> 48 | (let [v [1 2 3]] 49 | (match [v] 50 | [[1 1 1]] :a0 51 | [[1 2 1]] :a1 52 | [[1 2 _]] :a2)) 53 | ;; => :a2 54 | (ann-form (U nil ':a0 ':a1 ':a2))) 55 | 56 | (-> 57 | (let [v [3 2 3]] 58 | (match [v] 59 | [[1 1 3]] :a0 60 | [[2 & r]] :a1 61 | [[3 & r]] :a2)) 62 | ;; => :a2 63 | ; :a0 is unreachable 64 | (ann-form (U nil ':a1 ':a2))) 65 | 66 | #_(-> 67 | '(let [x '(1 2 3)] 68 | (match [x] 69 | [[1 (:or 3 4) 3]] :a0 70 | [[1 (:or 2 3) 3]] :a1)) 71 | macroexpand 72 | pprint) 73 | 74 | (-> 75 | (let [x '(1 2 3)] 76 | (match [x] 77 | [[1 (:or 3 4) 3]] :a0 78 | [[1 (:or 2 3) 3]] :a1)) 79 | ;; => :a1 80 | (ann-form (U nil ':a0 ':a1))) 81 | 82 | (-> 83 | '(let [x {:a 3}] 84 | (match [x] 85 | [{:a (:or 1 2)}] :a0 86 | [{:a (:or 3 4)}] :a1)) 87 | macroexpand 88 | pprint) 89 | ;; => :a1 90 | ) 91 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/check/try.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.core.typed.checker.check.try 10 | (:require [clojure.core.typed.checker.utils :as u] 11 | [clojure.core.typed.util-vars :as vs] 12 | [clojure.core.typed.checker.type-rep :as r] 13 | [clojure.core.typed.checker.check-below :as below] 14 | [clojure.core.typed.checker.filter-ops :as fo] 15 | [clojure.core.typed.checker.object-rep :as o] 16 | [clojure.core.typed.checker.type-ctors :as c])) 17 | 18 | (defn combine-rets [rs] 19 | {:pre [(seq rs) 20 | (every? r/TCResult? rs)] 21 | :post [(r/TCResult? %)]} 22 | (r/ret (apply c/Un (map r/ret-t rs)) 23 | (fo/-FS (apply fo/-or (map (comp :then r/ret-f) rs)) 24 | (apply fo/-or (map (comp :else r/ret-f) rs))) 25 | (if (apply = (map r/ret-o rs)) 26 | (r/ret-o (first rs)) 27 | o/-empty) 28 | (r/-flow (apply fo/-or (map (comp :normal r/ret-flow) rs))))) 29 | 30 | ; filters don't propagate between components of a `try`, nor outside of it. 31 | (defn check-try [check {:keys [body catches finally] :as expr} expected] 32 | (let [chk #(check % expected) 33 | cbody (chk body) 34 | ;_ (prn "cbody ret" (u/expr-type cbody)) 35 | ;_ (prn cbody) 36 | ccatches (mapv chk catches) 37 | ;_ (prn "ccatches ret" (mapv u/expr-type ccatches)) 38 | ; finally result is thrown away 39 | cfinally (when finally 40 | (check finally)) 41 | ret (binding [vs/*current-expr* expr] 42 | (below/maybe-check-below 43 | (combine-rets 44 | (map u/expr-type (concat [cbody] ccatches))) 45 | expected))] 46 | ;(prn "try ret" ret) 47 | (assoc expr 48 | :body cbody 49 | :catches ccatches 50 | :finally cfinally 51 | u/expr-type ret))) 52 | -------------------------------------------------------------------------------- /src/main/clojure/clojure/core/typed/checker/datatype_env.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^:skip-wiki clojure.core.typed.checker.datatype-env 10 | (:require [clojure.core.typed.contract-utils :as con] 11 | [clojure.core.typed.errors :as err] 12 | [clojure.core.typed.checker.type-rep :as r] 13 | [clojure.core.typed.current-impl :as impl] 14 | [clojure.core.typed :as t] 15 | [clojure.core.typed.env :as env])) 16 | 17 | (t/ann ^:no-check clojure.core.typed.errors/deprecated-warn [String -> nil]) 18 | (t/ann ^:no-check clojure.core.typed.errors/int-error [String -> t/Nothing]) 19 | 20 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21 | ;; Datatype Env 22 | 23 | (t/defalias DataTypeEnv 24 | "An Environment mapping datatype symbols to types." 25 | (t/Map t/Sym (t/U (t/Delay r/Type) r/Type))) 26 | 27 | (defn datatype-env [] 28 | {:post [(map? %)]} 29 | (get (env/deref-checker) impl/current-datatype-env-kw {})) 30 | 31 | (t/ann ^:no-check add-datatype [t/Sym r/Type -> nil]) 32 | 33 | (def add-datatype impl/add-datatype) 34 | 35 | (t/ann get-datatype [t/Sym -> (t/U nil r/Type)]) 36 | (defn get-datatype 37 | "Get the datatype with class symbol sym. 38 | Returns nil if not found." 39 | [sym] 40 | {:pre [(symbol? sym)] 41 | :post [((some-fn nil? r/DataType? r/TypeFn?) %)]} 42 | (force (get (datatype-env) sym))) 43 | 44 | (t/ann resolve-datatype [t/Sym -> r/Type]) 45 | (defn resolve-datatype 46 | "Same as get-datatype, but fails if datatype is not found." 47 | [sym] 48 | {:pre [(symbol? sym)] 49 | :post [(r/Type? %)]} 50 | (let [d (get-datatype sym)] 51 | (when-not d 52 | (err/int-error (str "Could not resolve DataType: " sym))) 53 | d)) 54 | 55 | (t/ann reset-datatype-env! [DataTypeEnv -> DataTypeEnv]) 56 | (defn reset-datatype-env! [new-env] 57 | {:pre [(map? new-env)] 58 | :post [(nil? %)]} 59 | (env/swap-checker! assoc impl/current-datatype-env-kw new-env) 60 | nil) 61 | --------------------------------------------------------------------------------