From 57f7c6ea164271d92cec5a12d22043c7029e3de2 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Thu, 4 Mar 2021 09:41:25 -0600 Subject: [PATCH 01/78] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 300eaff009..675fcd196d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ clojure clojure jar - 1.10.3 + 1.11.1-master-SNAPSHOT http://clojure.org/ Clojure core environment and runtime library. @@ -30,7 +30,7 @@ scm:git:git@github.com:clojure/clojure.git scm:git:git@github.com:clojure/clojure.git git@github.com:clojure/clojure.git - clojure-1.10.3 + HEAD From 3c9307e27479d450e3f1cdf7903458b83ebf52d7 Mon Sep 17 00:00:00 2001 From: Fogus Date: Thu, 18 Mar 2021 08:06:18 -0400 Subject: [PATCH 02/78] CLJ-2603: Added support for trailing, conj-able element in map-destructuring support for seqs. Moved to use of PersistentArrayMap/createAsIfByAssoc in map destructuring context. Modified docstrings for let and fn to add mention of destructuring forms. Finally, added seq-to-map-for-destructuring to help developers get the same behavior in their own macros. Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 37 +++++++++--- src/jvm/clojure/lang/ArraySeq.java | 7 +++ src/jvm/clojure/lang/PersistentArrayMap.java | 56 ++++++++++++++++++- test/clojure/test_clojure/data_structures.clj | 31 ++++++++++ 4 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 2c7334febc..b27dff8145 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -4371,7 +4371,19 @@ :static true} ([] (. clojure.lang.PersistentArrayMap EMPTY)) ([& keyvals] - (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array keyvals)))) + (let [ary (to-array keyvals)] + (if (odd? (alength ary)) + (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) + (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))))) + +(defn seq-to-map-for-destructuring + "Builds a map from a seq as described in + https://clojure.org/reference/special_forms#keyword-arguments" + {:added "1.11"} + [s] + (if (next s) + (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) + (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY))) ;;redefine let and loop with destructuring (defn destructure [bindings] @@ -4419,7 +4431,11 @@ gmapseq (with-meta gmap {:tag 'clojure.lang.ISeq}) defaults (:or b)] (loop [ret (-> bvec (conj gmap) (conj v) - (conj gmap) (conj `(if (seq? ~gmap) (clojure.lang.PersistentHashMap/create (seq ~gmapseq)) ~gmap)) + (conj gmap) (conj `(if (seq? ~gmap) + (if (next ~gmapseq) + (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array ~gmapseq)) + (if (seq ~gmapseq) (first ~gmapseq) clojure.lang.PersistentArrayMap/EMPTY)) + ~gmap)) ((fn [ret] (if (:as b) (conj ret (:as b) gmap) @@ -4468,10 +4484,15 @@ (defmacro let "binding => binding-form init-expr + binding-form => name, or destructuring-form + destructuring-form => map-destructure-form, or seq-destructure-form Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts - therein." + therein. + + See https://clojure.org/reference/special_forms#binding-forms for + more information about destructuring." {:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]} [bindings & body] (assert-args @@ -4499,12 +4520,14 @@ ;redefine fn with destructuring and pre/post conditions (defmacro fn - "params => positional-params* , or positional-params* & next-param + "params => positional-params*, or positional-params* & rest-param positional-param => binding-form - next-param => binding-form - name => symbol + rest-param => binding-form + binding-form => name, or destructuring-form + + Defines a function. - Defines a function" + See https://clojure.org/reference/special_forms#fn for more information" {:added "1.0", :special-form true, :forms '[(fn name? [params* ] exprs*) (fn name? ([params* ] exprs*)+)]} [& sigs] diff --git a/src/jvm/clojure/lang/ArraySeq.java b/src/jvm/clojure/lang/ArraySeq.java index 597a5410de..49a74b660d 100644 --- a/src/jvm/clojure/lang/ArraySeq.java +++ b/src/jvm/clojure/lang/ArraySeq.java @@ -142,6 +142,13 @@ public int lastIndexOf(Object o) { return -1; } +public Object[] toArray(){ + int sz = this.array.length - this.i; + Object[] ret = new Object[sz]; + System.arraycopy(this.array, i, ret, 0, sz); + return ret; +} + //////////////////////////////////// specialized primitive versions /////////////////////////////// static public class ArraySeq_int extends ASeq implements IndexedSeq, IReduce{ diff --git a/src/jvm/clojure/lang/PersistentArrayMap.java b/src/jvm/clojure/lang/PersistentArrayMap.java index 27b860e5d5..1f86fd80aa 100644 --- a/src/jvm/clojure/lang/PersistentArrayMap.java +++ b/src/jvm/clojure/lang/PersistentArrayMap.java @@ -76,9 +76,61 @@ static public PersistentArrayMap createWithCheck(Object[] init){ return new PersistentArrayMap(init); } +/** + *

This method attempts to find resue the given array as the basis for an array map as quickly as possible.

+ * + *

If a trailing element exists in the array or it contains duplicate keys then it delegates to the complex path.

+ **/ static public PersistentArrayMap createAsIfByAssoc(Object[] init){ - if ((init.length & 1) == 1) - throw new IllegalArgumentException(String.format("No value supplied for key: %s", init[init.length-1])); + boolean complexPath, hasTrailing; + complexPath = hasTrailing = ((init.length & 1) == 1); + + for(int i=0;((i< init.length) && !complexPath);i += 2) + { + for(int j=0;jThis method handles the default case of an array containing alternating key/value pairs.

+ *

It will reallocate a smaller init array if duplicate keys are found.

+ * + *

If a trailing element is found then will attempt to add it to the resulting map as if by conj.

+ *

No guarantees about the order of the keys in the trailing element are made.

+ **/ +private static PersistentArrayMap createAsIfByAssocComplexPath(Object[] init, boolean hasTrailing){ + if(hasTrailing) + { + IPersistentCollection trailing = PersistentArrayMap.EMPTY.cons(init[init.length-1]); + init = growSeedArray(init, trailing); + } + // If this looks like it is doing busy-work, it is because it // is achieving these goals: O(n^2) run time like // createWithCheck(), never modify init arg, and only diff --git a/test/clojure/test_clojure/data_structures.clj b/test/clojure/test_clojure/data_structures.clj index 69baf137c6..854560466b 100644 --- a/test/clojure/test_clojure/data_structures.clj +++ b/test/clojure/test_clojure/data_structures.clj @@ -1330,3 +1330,34 @@ (is (= (hash (->Rec 1 1)) (hash (assoc r :a 1)))) (is (= (hash (->Rec 1 1)) (hash (dissoc r2 :c)))) (is (= (hash (->Rec 1 1)) (hash (dissoc (assoc r :c 1) :c)))))) + +(deftest singleton-map-in-destructure-context + (let [sample-map {:a 1 :b 2} + {:keys [a] :as m1} (list sample-map)] + (is (= m1 sample-map)) + (is (= a 1)))) + +(deftest trailing-map-destructuring + (let [sample-map {:a 1 :b 2} + add (fn [& {:keys [a b]}] (+ a b)) + addn (fn [n & {:keys [a b]}] (+ n a b))] + (testing "that kwargs are applied properly given a map in place of the key/val pairs" + (is (= 3 (add :a 1 :b 2))) + (is (= 3 (add {:a 1 :b 2}))) + (is (= 13 (addn 10 :a 1 :b 2))) + (is (= 13 (addn 10 {:a 1 :b 2}))) + (is (= 103 ((partial addn 100) :a 1 {:b 2}))) + (is (= 103 ((partial addn 100 :a 1) {:b 2}))) + (is (= 107 ((partial addn 100 :a 1) {:a 5 :b 2})))) + (testing "built maps" + (let [{:as m1} (list :a 1 :b 2) + {:as m2} (list :a 1 :b 2 {:c 3}) + {:as m3} (list :a 1 :b 2 {:a 0}) + {:keys [a4] :as m4} (list nil)] + (= m1 {:a 1 :b 2}) + (= m2 {:a 1 :b 2 :c 3}) + (= m3 {:a 0 :b 2}) + (= m1 (seq-to-map-for-destructuring (list :a 1 :b 2))) + (= m2 (seq-to-map-for-destructuring (list :a 1 :b 2 {:c 3}))) + (= m3 (seq-to-map-for-destructuring (list :a 1 :b 2 {:a 0}))) + (= a4 nil))))) From 9249412dbd7e761670c4f05b399a10460230707d Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 18 Mar 2021 13:57:21 -0500 Subject: [PATCH 03/78] update release plugin versions --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 675fcd196d..86f4c48ff8 100644 --- a/pom.xml +++ b/pom.xml @@ -207,7 +207,7 @@ instead, push SCM changes in Hudson configuration --> org.apache.maven.plugins maven-release-plugin - 2.4.1 + 2.5.3 false true @@ -227,7 +227,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.7 + 1.6.8 true From af60514c308abee051e3cb6e3ee16a69c6272ed5 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Thu, 18 Mar 2021 14:00:50 -0500 Subject: [PATCH 04/78] [maven-release-plugin] prepare release clojure-1.11.0-alpha1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 86f4c48ff8..00aaed878d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ clojure clojure jar - 1.11.1-master-SNAPSHOT + 1.11.0-alpha1 http://clojure.org/ Clojure core environment and runtime library. @@ -30,7 +30,7 @@ scm:git:git@github.com:clojure/clojure.git scm:git:git@github.com:clojure/clojure.git git@github.com:clojure/clojure.git - HEAD + clojure-1.11.0-alpha1 From b1b88dd25373a86e41310a525a21b497799dbbf2 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Thu, 18 Mar 2021 14:00:50 -0500 Subject: [PATCH 05/78] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 00aaed878d..efb331d86a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ clojure clojure jar - 1.11.0-alpha1 + 1.11.0-master-SNAPSHOT http://clojure.org/ Clojure core environment and runtime library. @@ -30,7 +30,7 @@ scm:git:git@github.com:clojure/clojure.git scm:git:git@github.com:clojure/clojure.git git@github.com:clojure/clojure.git - clojure-1.11.0-alpha1 + HEAD From a29f9b911b569b0a4890f320ec8f946329bbe0fd Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 24 Jun 2021 13:35:59 -0500 Subject: [PATCH 06/78] refresh contributing and add pull request template --- .github/PULL_REQUEST_TEMPLATE | 5 ++++ CONTRIBUTING.md | 43 ++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000000..31b549a89c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,5 @@ +Hi! This project does not accept pull requests. + +Please see the guidelines for contribution on how to file issues or provide patches: + +https://github.com/clojure/clojure/blob/master/CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06b2fc0581..84f0aee84b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1 +1,42 @@ -If you'd like to submit a patch, please follow the [contributing guidelines](http://clojure.org/contributing). +Hi! Thanks for your interest in Clojure! + +## I want to ask a question + +If you have a question about Clojure, please use the official Ask Clojure forum at https://ask.clojure.org. This forum is monitored by the Clojure maintainers. + +## I want to discuss an idea + +There are many interactive Clojure forums for discussion and you can find a list at [Clojure Discussion](https://clojure.org/community/resources#_clojure_discussion). + +## I want to file a bug / suggest an enhancement + +Please file it as a question on https://ask.clojure.org with the tag "problem" (possible bugs) or "request" (enhancements). + +## I want to provide a patch / PR + +If you would like to contribute patches, the Clojure dev process is described in detail at https://clojure.org/dev. + +In short, this process requires: + +- [Signing the Contributor Agreement](https://clojure.org/dev/contributor_agreement) +- [Requesting jira access](https://clojure.atlassian.net/servicedesk/customer/portal/1) + +This project does not accept pull requests. + +## I am looking for official documentation + +You can find official documentation on the Clojure web site: + +* Reference docs https://clojure.org/reference +* Tutorials and guides: https://clojure.org/guides +* API: https://clojure.org/api/api + +## What release should I use? + +Find the current release info here: + +https://clojure.org/releases/downloads + +A list of all releases can be found here: + +https://clojure.org/releases/downloads_older From f96eef2892eaef55dbbdbf7f3b4b818be06f6ddd Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 14 Sep 2021 08:24:35 -0500 Subject: [PATCH 07/78] CLJ-2123 Add :as-alias option to require like :as but does not load Signed-off-by: Alex Miller --- build.xml | 2 +- src/clj/clojure/core.clj | 35 +++++++++++------ test/clojure/test_clojure/ns_libs.clj | 38 +++++++++++++++++++ .../test_clojure/ns_libs_load_later.clj | 12 ++++++ 4 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 test/clojure/test_clojure/ns_libs_load_later.clj diff --git a/build.xml b/build.xml index 4d29bbf9a2..fd03afb417 100644 --- a/build.xml +++ b/build.xml @@ -113,7 +113,7 @@ unless="maven.test.skip"> + value="#{clojure.test-clojure.compilation.load-ns clojure.test-clojure.ns-libs-load-later}"/> diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index b27dff8145..8a94de15bf 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -5945,7 +5945,7 @@ (name lib) prefix) (let [lib (if prefix (symbol (str prefix \. lib)) lib) opts (apply hash-map options) - {:keys [as reload reload-all require use verbose]} opts + {:keys [as reload reload-all require use verbose as-alias]} opts loaded (contains? @*loaded-libs* lib) load (cond reload-all load-all @@ -5955,21 +5955,28 @@ filter-opts (select-keys opts '(:exclude :only :rename :refer)) undefined-on-entry (not (find-ns lib))] (binding [*loading-verbosely* (or *loading-verbosely* verbose)] - (if load - (try - (load lib need-ns require) - (catch Exception e - (when undefined-on-entry - (remove-ns lib)) - (throw e))) - (throw-if (and need-ns (not (find-ns lib))) - "namespace '%s' not found" lib)) + (if as-alias + (when (not (find-ns lib)) + (create-ns lib)) + (if load + (try + (load lib need-ns require) + (catch Exception e + (when undefined-on-entry + (remove-ns lib)) + (throw e))) + (throw-if (and need-ns (not (find-ns lib))) + "namespace '%s' not found" lib))) (when (and need-ns *loading-verbosely*) (printf "(clojure.core/in-ns '%s)\n" (ns-name *ns*))) (when as (when *loading-verbosely* (printf "(clojure.core/alias '%s '%s)\n" as lib)) (alias as lib)) + (when as-alias + (when *loading-verbosely* + (printf "(clojure.core/alias '%s '%s)\n" as-alias lib)) + (alias as-alias lib)) (when (or use (:refer filter-opts)) (when *loading-verbosely* (printf "(clojure.core/refer '%s" lib) @@ -5986,7 +5993,7 @@ opts (interleave flags (repeat true)) args (filter (complement keyword?) args)] ; check for unsupported options - (let [supported #{:as :reload :reload-all :require :use :verbose :refer} + (let [supported #{:as :reload :reload-all :require :use :verbose :refer :as-alias} unsupported (seq (remove supported flags))] (throw-if unsupported (apply str "Unsupported option(s) supplied: " @@ -6050,6 +6057,9 @@ Recognized options: :as takes a symbol as its argument and makes that symbol an alias to the lib's namespace in the current namespace. + :as-alias takes a symbol as its argument and aliases like :as, however + the lib will not be loaded. If the lib has not been loaded, a new + empty namespace will be created (as with create-ns). :refer takes a list of symbols to refer from the namespace or the :all keyword to bring in all public vars. @@ -6066,9 +6076,10 @@ A flag is a keyword. Recognized flags: :reload, :reload-all, :verbose :reload forces loading of all the identified libs even if they are - already loaded + already loaded (has no effect on libspecs using :as-alias) :reload-all implies :reload and also forces loading of all libs that the identified libs directly or indirectly load via require or use + (has no effect on libspecs using :as-alias) :verbose triggers printing information about each load, alias, and refer Example: diff --git a/test/clojure/test_clojure/ns_libs.clj b/test/clojure/test_clojure/ns_libs.clj index 0e470d7394..a9f4f97f71 100644 --- a/test/clojure/test_clojure/ns_libs.clj +++ b/test/clojure/test_clojure/ns_libs.clj @@ -103,3 +103,41 @@ (is (thrown-with-cause-msg? clojure.lang.Compiler$CompilerException #"defrecord and deftype fields must be symbols, user\.MyType had: :key1" (eval '(deftype MyType [:key1]))))) + +(deftest require-as-alias + ;; :as-alias does not load + (require '[not.a.real.ns [foo :as-alias foo] + [bar :as-alias bar]]) + (let [aliases (ns-aliases *ns*) + foo-ns (get aliases 'foo) + bar-ns (get aliases 'bar)] + (is (= 'not.a.real.ns.foo (ns-name foo-ns))) + (is (= 'not.a.real.ns.bar (ns-name bar-ns)))) + + (is (= :not.a.real.ns.foo/baz (read-string "::foo/baz"))) + + ;; can use :as-alias in use + (use '[dummy.example1 :as-alias e1]) + (let [aliases (ns-aliases *ns*)] + (is (= 'dummy.example1 (ns-name (get aliases 'e1))))) + + ;; can use both :as and :as-alias + (require '[clojure.set :as n1 :as-alias n2]) + (let [aliases (ns-aliases *ns*)] + (is (= 'clojure.set (ns-name (get aliases 'n1)))) + (is (= 'clojure.set (ns-name (get aliases 'n2)))))) + +(deftest require-as-alias-then-load-later + ;; alias but don't load + (require '[clojure.test-clojure.ns-libs-load-later :as-alias alias-now]) + (is (contains? (ns-aliases *ns*) 'alias-now)) + (is (not (nil? (find-ns 'clojure.test-clojure.ns-libs-load-later)))) + + ;; not loaded! + (is (nil? (resolve 'alias-now/example))) + + ;; load + (require 'clojure.test-clojure.ns-libs-load-later) + + ;; now loaded! + (is (not (nil? (resolve 'alias-now/example))))) \ No newline at end of file diff --git a/test/clojure/test_clojure/ns_libs_load_later.clj b/test/clojure/test_clojure/ns_libs_load_later.clj new file mode 100644 index 0000000000..2a45b86ab9 --- /dev/null +++ b/test/clojure/test_clojure/ns_libs_load_later.clj @@ -0,0 +1,12 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +;; used by clojure.test-clojure.ns-libs/require-as-alias-then-load-later +(ns clojure.test-clojure.ns-libs-load-later) + +(defn example [] true) From 709397c300b6d5a2258c9568dda898577e74ad0c Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 7 Sep 2021 13:09:25 -0400 Subject: [PATCH 08/78] CLJ-2651: Added implementation of update-vals and tests. Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 16 ++++++++++++++++ test/clojure/test_clojure/other_functions.clj | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 8a94de15bf..1b1da5c215 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -7926,3 +7926,19 @@ fails, attempts to require sym's namespace and retries." [x] (force tap-loop) (.offer tapq (if (nil? x) ::tap-nil x))) + +(defn update-vals + "m f => {k (f v) ...} + + Given a map m and a function f of 1-argument, returns a new map where the keys of m + are mapped to result of applying f to the corresponding values of m." + {:added "1.11"} + [m f] + (with-meta + (persistent! + (reduce-kv (fn [acc k v] (assoc! acc k (f v))) + (if (instance? clojure.lang.IEditableCollection m) + (transient m) + (transient {})) + m)) + (meta m))) diff --git a/test/clojure/test_clojure/other_functions.clj b/test/clojure/test_clojure/other_functions.clj index 0f3093d183..e0f7beede6 100644 --- a/test/clojure/test_clojure/other_functions.clj +++ b/test/clojure/test_clojure/other_functions.clj @@ -379,3 +379,12 @@ ;; rest arity {:a 5} (update {:a 1} :a + 1 1 1 1) {:a 6} (update {:a 1} :a + 1 1 1 1 1))) + +(deftest test-update-vals + (let [inm (with-meta {:a 1 :b 2} {:has :meta})] + (are [result expr] (= result expr) + {:a 2 :b 3} (update-vals inm inc) + {:has :meta} (meta (update-vals inm inc)) + {0 2 2 4} (update-vals (hash-map 0 1 2 3) inc) + {0 2 2 4} (update-vals (array-map 0 1 2 3) inc) + {0 2 2 4} (update-vals (sorted-map 2 3 0 1) inc)))) From b0ca4b8056b1718b16d31b89910a03be4b0187cd Mon Sep 17 00:00:00 2001 From: "Howard M. Lewis Ship" Date: Fri, 1 Apr 2016 14:36:24 -0700 Subject: [PATCH 09/78] CLJ-1098: Add clojure.test api to run single test with fixtures and report Signed-off-by: Alex Miller --- src/clj/clojure/test.clj | 35 +++++++++++++++++++ test/clojure/test_clojure/run_single_test.clj | 33 +++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/clojure/test_clojure/run_single_test.clj diff --git a/src/clj/clojure/test.clj b/src/clj/clojure/test.clj index fcb3224846..30aae631b2 100644 --- a/src/clj/clojure/test.clj +++ b/src/clj/clojure/test.clj @@ -793,3 +793,38 @@ [summary] (and (zero? (:fail summary 0)) (zero? (:error summary 0)))) + +(defn run-test-var + "Runs the tests for a single Var, with fixtures executed around the test, and summary output after." + {:added "1.9"} + [v] + (binding [*report-counters* (ref *initial-report-counters*)] + (let [ns-obj (-> v meta :ns) + summary (do + (do-report {:type :begin-test-ns + :ns ns-obj}) + (test-vars [v]) + (do-report {:type :end-test-ns + :ns ns-obj}) + (assoc @*report-counters* :type :summary))] + (do-report summary) + summary))) + +(defmacro run-test + "Runs a single test. + + Because the intent is to run a single test, there is no check for the namespace test-ns-hook." + {:added "1.9"} + [test-symbol] + (let [test-var (resolve test-symbol)] + (cond + (nil? test-var) + (binding [*out* *err*] + (println "Unable to resolve" test-symbol "to a test function.")) + + (not (-> test-var meta :test)) + (binding [*out* *err*] + (println test-symbol "is not a test.")) + + :else + `(run-test-var ~test-var)))) diff --git a/test/clojure/test_clojure/run_single_test.clj b/test/clojure/test_clojure/run_single_test.clj new file mode 100644 index 0000000000..abf1084c0a --- /dev/null +++ b/test/clojure/test_clojure/run_single_test.clj @@ -0,0 +1,33 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns clojure.test-clojure.run-single-test + (:require [clojure.test :refer [is deftest run-test run-tests]] + [clojure.test-helper :refer [with-err-string-writer]] + [clojure.test-clojure.test-fixtures :as tf])) + +(defn not-a-test + []) + +(defmacro should-print-to-err + [re & body] + `(is (re-find ~re (with-err-string-writer ~@body)))) + +(deftest reports-missing-var + (should-print-to-err #"^Unable to resolve .*/function-missing to a test function.*" + (let [result (eval `(run-test function-missing))] + (is (nil? result))))) + +(deftest reports-non-test-var + (should-print-to-err #"^.*/not-a-test is not a test.*" + (let [result (eval `(run-test not-a-test))] + (is (nil? result))))) + +(deftest can-run-test-with-fixtures + (is (= {:test 1, :pass 2, :fail 0, :error 0, :type :summary} + (run-test tf/can-use-once-fixtures)))) From bd4c42dc7946cb015b8d0699596662aa68bcdc89 Mon Sep 17 00:00:00 2001 From: Marc O'Morain Date: Tue, 14 Sep 2021 08:29:33 -0500 Subject: [PATCH 10/78] CLJ-2350 Improve keyword aritiy exception message When calling a keyword with the wrong number of arguments (0, or more than 2), throw an ArityException rather than IllegalArgumentException. The ArityException class has improved error messages over the custom IllegalArgumentException thrown by Keyword.java. Signed-off-by: Alex Miller --- src/jvm/clojure/lang/Keyword.java | 50 +++++++++++++++----------- test/clojure/test_clojure/keywords.clj | 6 ++++ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/jvm/clojure/lang/Keyword.java b/src/jvm/clojure/lang/Keyword.java index 02d21326a2..145df4f73b 100644 --- a/src/jvm/clojure/lang/Keyword.java +++ b/src/jvm/clojure/lang/Keyword.java @@ -93,13 +93,21 @@ public String toString(){ return _str; } +/** + * @deprecated CLJ-2350: This function is no longer called, but has not been + * removed to maintain the public interface. + */ public Object throwArity(){ throw new IllegalArgumentException("Wrong number of args passed to keyword: " + toString()); } +Object throwArity(int n) { + throw new ArityException(n, toString()); +} + public Object call() { - return throwArity(); + return throwArity(0); } public void run(){ @@ -107,7 +115,7 @@ public void run(){ } public Object invoke() { - return throwArity(); + return throwArity(0); } public int compareTo(Object o){ @@ -146,98 +154,98 @@ final public Object invoke(Object obj, Object notFound) { } public Object invoke(Object arg1, Object arg2, Object arg3) { - return throwArity(); + return throwArity(3); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) { - return throwArity(); + return throwArity(4); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - return throwArity(); + return throwArity(5); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - return throwArity(); + return throwArity(6); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - return throwArity(); + return throwArity(7); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - return throwArity(); + return throwArity(8); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - return throwArity(); + return throwArity(9); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - return throwArity(); + return throwArity(10); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11) { - return throwArity(); + return throwArity(11); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) { - return throwArity(); + return throwArity(12); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) { - return throwArity(); + return throwArity(13); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) { - return throwArity(); + return throwArity(14); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15) { - return throwArity(); + return throwArity(15); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16) { - return throwArity(); + return throwArity(16); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17) { - return throwArity(); + return throwArity(17); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18) { - return throwArity(); + return throwArity(18); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) { - return throwArity(); + return throwArity(19); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) { - return throwArity(); + return throwArity(20); } public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, @@ -245,7 +253,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, Object... args) { - return throwArity(); + return throwArity(20 + args.length); } diff --git a/test/clojure/test_clojure/keywords.clj b/test/clojure/test_clojure/keywords.clj index 9ef86d7dd2..614fbc14e2 100644 --- a/test/clojure/test_clojure/keywords.clj +++ b/test/clojure/test_clojure/keywords.clj @@ -23,3 +23,9 @@ (are [result lookup] (= result (find-keyword this-ns lookup)) ::foo "foo" nil (str absent-keyword-sym))))) + +(deftest arity-exceptions + (is (thrown-with-msg? IllegalArgumentException #"Wrong number of args \(0\) passed to: :kw" (:kw))) + (is (thrown-with-msg? IllegalArgumentException #"Wrong number of args \(20\) passed to: :foo/bar" (apply :foo/bar (range 20)))) + (is (thrown-with-msg? IllegalArgumentException #"Wrong number of args \(21\) passed to: :foo/bar" (apply :foo/bar (range 21)))) + (is (thrown-with-msg? IllegalArgumentException #"Wrong number of args \(22\) passed to: :foo/bar" (apply :foo/bar (range 22))))) From 383ed2adce7e7d09fccef0713a65f44242d74c8f Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Fri, 23 Nov 2018 11:00:28 +0100 Subject: [PATCH 11/78] CLJ-2444: fix typo in test-vars docstring Signed-off-by: Alex Miller --- src/clj/clojure/test.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/clojure/test.clj b/src/clj/clojure/test.clj index 30aae631b2..ce6e025a0f 100644 --- a/src/clj/clojure/test.clj +++ b/src/clj/clojure/test.clj @@ -721,8 +721,8 @@ (do-report {:type :end-test-var, :var v})))) (defn test-vars - "Groups vars by their namespace and runs test-vars on them with - appropriate fixtures applied." + "Groups vars by their namespace and runs test-var on them with + appropriate fixtures applied." {:added "1.6"} [vars] (doseq [[ns vars] (group-by (comp :ns meta) vars)] From d56812cf2e9f7a317f9b603ef4c9f07bf1bed281 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 14 Sep 2021 09:57:09 -0500 Subject: [PATCH 12/78] CLJ-2600 Don't block realized? of delay on pending result Signed-off-by: Alex Miller --- src/jvm/clojure/lang/Delay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jvm/clojure/lang/Delay.java b/src/jvm/clojure/lang/Delay.java index 262c9c1a43..ffd418962d 100644 --- a/src/jvm/clojure/lang/Delay.java +++ b/src/jvm/clojure/lang/Delay.java @@ -54,7 +54,7 @@ public Object deref() { return val; } -synchronized public boolean isRealized(){ +public boolean isRealized(){ return fn == null; } } From fba284a0da101791269ad7ae4cfd61219535631a Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 12 Feb 2019 11:14:58 -0600 Subject: [PATCH 13/78] CLJ-1509 AOT compile more Clojure namespaces Signed-off-by: Alex Miller --- build.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.xml b/build.xml index fd03afb417..80c40f69de 100644 --- a/build.xml +++ b/build.xml @@ -82,6 +82,9 @@ + + + From 894aec0078ff2b58ff12454978b79b163ecc9e4c Mon Sep 17 00:00:00 2001 From: Keyhan Vakil Date: Thu, 16 Aug 2018 21:56:46 -0400 Subject: [PATCH 14/78] CLJ-2387 fixed off-by-one in socket server port validation Signed-off-by: Alex Miller --- src/clj/clojure/core/server.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clj/clojure/core/server.clj b/src/clj/clojure/core/server.clj index f343aa76fe..48377d4127 100644 --- a/src/clj/clojure/core/server.clj +++ b/src/clj/clojure/core/server.clj @@ -51,7 +51,7 @@ "Validate server config options" [{:keys [name port accept] :as opts}] (doseq [prop [:name :port :accept]] (required opts prop)) - (when (or (not (integer? port)) (not (< -1 port 65535))) + (when (or (not (integer? port)) (not (<= 0 port 65535))) (throw (ex-info (str "Invalid socket server port: " port) opts)))) (defn- accept-connection From 69387c5e7d617ebe17ebaaa97344a1bb6a5f0817 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Fri, 11 Jun 2021 15:41:25 +0200 Subject: [PATCH 15/78] CLJ-2636: Get rid of reflection on java.util.Properties when defining *clojure-version* Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 1b1da5c215..99a967750c 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -7088,7 +7088,8 @@ fails, attempts to require sym's namespace and retries." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; -(let [properties (with-open [version-stream (.getResourceAsStream +(let [^java.util.Properties + properties (with-open [version-stream (.getResourceAsStream (clojure.lang.RT/baseLoader) "clojure/version.properties")] (doto (new java.util.Properties) From 736c7a05cc94716778b383b99eef1090d031ed2d Mon Sep 17 00:00:00 2001 From: Fogus Date: Wed, 8 Sep 2021 08:08:39 -0400 Subject: [PATCH 16/78] CLJ-1879: Make old slow path (clojure.lang.IPersistentMap) reduce over seq of Map.Entry instances and extended to Object -- this is the new slow path. This change makes it general enough to deal with 'seqs to Map.Entries', detaching it from any fully-enumerable set of types. Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 13 +++++++++---- test/clojure/test_clojure/protocols.clj | 8 ++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 99a967750c..9a2bf3d5b4 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -6870,13 +6870,18 @@ fails, attempts to require sym's namespace and retries." init) ;;slow path default - clojure.lang.IPersistentMap - (kv-reduce + java.lang.Object + (kv-reduce [amap f init] - (reduce (fn [ret [k v]] (f ret k v)) init amap)) + (reduce (fn [ret ^java.util.Map$Entry me] + (f ret + (.getKey me) + (.getValue me))) + init + amap)) clojure.lang.IKVReduce - (kv-reduce + (kv-reduce [amap f init] (.kvreduce amap f init))) diff --git a/test/clojure/test_clojure/protocols.clj b/test/clojure/test_clojure/protocols.clj index 3072915481..ff556dcaed 100644 --- a/test/clojure/test_clojure/protocols.clj +++ b/test/clojure/test_clojure/protocols.clj @@ -674,3 +674,11 @@ (deftest test-leading-dashes (is (= 10 (-do-dashed (Dashed.)))) (is (= [10] (map -do-dashed [(Dashed.)])))) + +;; see CLJ-1879 + +(deftest test-base-reduce-kv + (is (= {1 :a 2 :b} + (reduce-kv #(assoc %1 %3 %2) + {} + (seq {:a 1 :b 2}))))) From 42d713929e8f7ecd77efe23384238d29bde62aba Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Fri, 20 Aug 2021 16:25:54 -0500 Subject: [PATCH 17/78] CLJ-2649 Fix order of checks in some-fn and every-pred for 3 predicate case to match other unrollings Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 8 ++++---- test/clojure/test_clojure/other_functions.clj | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 9a2bf3d5b4..2ab8f59b30 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -7461,8 +7461,8 @@ fails, attempts to require sym's namespace and retries." (fn ep3 ([] true) ([x] (boolean (and (p1 x) (p2 x) (p3 x)))) - ([x y] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y)))) - ([x y z] (boolean (and (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z)))) + ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y)))) + ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z)))) ([x y z & args] (boolean (and (ep3 x y z) (every? #(and (p1 %) (p2 %) (p3 %)) args)))))) ([p1 p2 p3 & ps] @@ -7501,8 +7501,8 @@ fails, attempts to require sym's namespace and retries." (fn sp3 ([] nil) ([x] (or (p1 x) (p2 x) (p3 x))) - ([x y] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y))) - ([x y z] (or (p1 x) (p2 x) (p3 x) (p1 y) (p2 y) (p3 y) (p1 z) (p2 z) (p3 z))) + ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y))) + ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z))) ([x y z & args] (or (sp3 x y z) (some #(or (p1 %) (p2 %) (p3 %)) args))))) ([p1 p2 p3 & ps] diff --git a/test/clojure/test_clojure/other_functions.clj b/test/clojure/test_clojure/other_functions.clj index e0f7beede6..ec60e78ebb 100644 --- a/test/clojure/test_clojure/other_functions.clj +++ b/test/clojure/test_clojure/other_functions.clj @@ -277,7 +277,9 @@ ((some-fn number? odd? #(> % 0)) 2 4 6 8 -10) ;; 3 preds, short-circuiting ((some-fn number? odd? #(> % 0)) 1 :a) + ((some-fn number? odd? #(> % 0)) :a 1) ((some-fn number? odd? #(> % 0)) 1 3 :a) + ((some-fn number? odd? #(> % 0)) :a 1 3) ((some-fn number? odd? #(> % 0)) 1 3 5 :a) ((some-fn number? odd? #(> % 0)) 1 :a 3 5 7) ;; 4 preds From 1d271d7bc74f64831985f89be1d814df2c5f046f Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 14 Sep 2021 10:56:58 -0400 Subject: [PATCH 18/78] CLJ-1959: Added implementation of update-keys and tests. Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 16 ++++++++++++++++ test/clojure/test_clojure/other_functions.clj | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 2ab8f59b30..41094f0c4d 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -7948,3 +7948,19 @@ fails, attempts to require sym's namespace and retries." (transient {})) m)) (meta m))) + +(defn update-keys + "m f => {(f k) v ...} + + Given a map m and a function f of 1-argument, returns a new map whose + keys are the result of applying f to the keys of m, mapped to the + corresponding values of m. + f must return a unique key for each key of m, else the behavior is undefined." + {:added "1.11"} + [m f] + (let [ret (persistent! + (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) + (transient {}) + m))] + (with-meta ret (meta m)))) + diff --git a/test/clojure/test_clojure/other_functions.clj b/test/clojure/test_clojure/other_functions.clj index ec60e78ebb..517f633fcc 100644 --- a/test/clojure/test_clojure/other_functions.clj +++ b/test/clojure/test_clojure/other_functions.clj @@ -390,3 +390,12 @@ {0 2 2 4} (update-vals (hash-map 0 1 2 3) inc) {0 2 2 4} (update-vals (array-map 0 1 2 3) inc) {0 2 2 4} (update-vals (sorted-map 2 3 0 1) inc)))) + +(deftest test-update-keys + (let [inm (with-meta {:a 1 :b 2} {:has :meta})] + (are [result expr] (= result expr) + {"a" 1 "b" 2} (update-keys inm name) + {:has :meta} (meta (update-keys inm name)) + {1 1 3 3} (update-keys (hash-map 0 1 2 3) inc) + {1 1 3 3} (update-keys (array-map 0 1 2 3) inc) + {1 1 3 3} (update-keys (sorted-map 2 3 0 1) inc)))) From 9a7d8035a0bb6850eaaf4e128e9ac6f2e3517942 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 14 Sep 2021 13:21:51 -0500 Subject: [PATCH 19/78] Fix :added metadata in new clojure.test fns --- src/clj/clojure/test.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/clojure/test.clj b/src/clj/clojure/test.clj index ce6e025a0f..0ab20a75a3 100644 --- a/src/clj/clojure/test.clj +++ b/src/clj/clojure/test.clj @@ -796,7 +796,7 @@ (defn run-test-var "Runs the tests for a single Var, with fixtures executed around the test, and summary output after." - {:added "1.9"} + {:added "1.11"} [v] (binding [*report-counters* (ref *initial-report-counters*)] (let [ns-obj (-> v meta :ns) @@ -814,7 +814,7 @@ "Runs a single test. Because the intent is to run a single test, there is no check for the namespace test-ns-hook." - {:added "1.9"} + {:added "1.11"} [test-symbol] (let [test-var (resolve test-symbol)] (cond From 4b46c4f6a0cee3e7a2db76dadbb99be2f64235f4 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 14 Sep 2021 14:59:48 -0500 Subject: [PATCH 20/78] Update dep core.specs.alpha 0.2.62 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index efb331d86a..3ec8bbb677 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ org.clojure core.specs.alpha - 0.2.56 + 0.2.62 org.clojure From 3ec386a11c426bd3cacb128ea994e3b3a5f6052f Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Tue, 14 Sep 2021 15:04:02 -0500 Subject: [PATCH 21/78] [maven-release-plugin] prepare release clojure-1.11.0-alpha2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3ec8bbb677..c8a4a44dae 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ clojure clojure jar - 1.11.0-master-SNAPSHOT + 1.11.0-alpha2 http://clojure.org/ Clojure core environment and runtime library. @@ -30,7 +30,7 @@ scm:git:git@github.com:clojure/clojure.git scm:git:git@github.com:clojure/clojure.git git@github.com:clojure/clojure.git - HEAD + clojure-1.11.0-alpha2 From b8132f92f3c3862aa6cdd8a72e4e74802a63f673 Mon Sep 17 00:00:00 2001 From: "Hudson @ build.clojure.org" Date: Tue, 14 Sep 2021 15:04:02 -0500 Subject: [PATCH 22/78] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c8a4a44dae..3ec8bbb677 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ clojure clojure jar - 1.11.0-alpha2 + 1.11.0-master-SNAPSHOT http://clojure.org/ Clojure core environment and runtime library. @@ -30,7 +30,7 @@ scm:git:git@github.com:clojure/clojure.git scm:git:git@github.com:clojure/clojure.git git@github.com:clojure/clojure.git - clojure-1.11.0-alpha2 + HEAD From 6e2ac1b2e29f89bca5dcd667c08a53d656bfef0c Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 23 Nov 2021 10:24:41 -0600 Subject: [PATCH 23/78] Update to spec.alpha 0.3.214 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3ec8bbb677..71c4378068 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ org.clojure spec.alpha - 0.2.194 + 0.3.214 org.clojure From bd507fac423ebd59a8f032369d75ce079ce88d40 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Mon, 22 Nov 2021 08:22:36 -0600 Subject: [PATCH 24/78] CLJ-2667 Add functions to parse a single long/double/uuid/boolean from a string Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 50 +++++++++++++++ test/clojure/test_clojure/parse.clj | 99 +++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 test/clojure/test_clojure/parse.clj diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 41094f0c4d..66e9f2655b 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -7964,3 +7964,53 @@ fails, attempts to require sym's namespace and retries." m))] (with-meta ret (meta m)))) +(defn- parsing-err + "Construct message for parsing for non-string parsing error" + ^String [val] + (str "Expected string, got " (if (nil? val) "nil" (-> val class .getName)))) + +(defn parse-long + {:doc "Parse string of decimal digits with optional leading -/+ and return a + Long value, or nil if parse fails" + :added "1.11"} + ^Long [^String s] + (if (string? s) + (try + (Long/valueOf s) + (catch NumberFormatException _ nil)) + (throw (IllegalArgumentException. (parsing-err s))))) + +(defn parse-double + {:doc "Parse string with floating point components and return a Double value, + or nil if parse fails. + + Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" + :added "1.11"} + ^Double [^String s] + (if (string? s) + (try + (Double/valueOf s) + (catch NumberFormatException _ nil)) + (throw (IllegalArgumentException. (parsing-err s))))) + +(defn parse-uuid + {:doc "Parse a string representing a UUID and return a java.util.UUID instance, + or nil if parse fails. + + Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" + :added "1.11"} + ^java.util.UUID [^String s] + (try + (java.util.UUID/fromString s) + (catch IllegalArgumentException _ nil))) + +(defn parse-boolean + {:doc "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" + :added "1.11"} + [^String s] + (if (string? s) + (case s + "true" true + "false" false + nil) + (throw (IllegalArgumentException. (parsing-err s))))) \ No newline at end of file diff --git a/test/clojure/test_clojure/parse.clj b/test/clojure/test_clojure/parse.clj new file mode 100644 index 0000000000..953beefb4d --- /dev/null +++ b/test/clojure/test_clojure/parse.clj @@ -0,0 +1,99 @@ +(ns clojure.test-clojure.parse + (:require + [clojure.test :refer :all] + [clojure.test.check :as chk] + [clojure.test.check.generators :as gen] + [clojure.test.check.properties :as prop]) + (:import + [java.util UUID])) + +(deftest test-parse-long + (are [s expected] + (= expected (parse-long s)) + "100" 100 + "+100" 100 + "0" 0 + "+0" 0 + "-0" 0 + "-42" -42 + "9223372036854775807" Long/MAX_VALUE + "+9223372036854775807" Long/MAX_VALUE + "-9223372036854775808" Long/MIN_VALUE + "077" 77) ;; leading 0s are ignored! (not octal) + + (are [s] ;; do not parse + (nil? (parse-long s)) + "0.3" ;; no float + "9223372036854775808" ;; past max long + "-9223372036854775809" ;; past min long + "0xA0" ;; no hex + "2r010")) ;; no radix support + +;; generative test - gen long -> str -> parse, compare +(deftest test-gen-parse-long + (let [res (chk/quick-check + 100000 + (prop/for-all* [gen/large-integer] + #(= % (-> % str parse-long))))] + (if (:result res) + (is true) ;; pass + (is (:result res) (pr-str res))))) + +(deftest test-parse-double + (are [s expected] + (= expected (parse-double s)) + "1.234" 1.234 + "+1.234" 1.234 + "-1.234" -1.234 + "+0" +0.0 + "-0.0" -0.0 + "0.0" 0.0 + "5" 5.0 + "Infinity" Double/POSITIVE_INFINITY + "-Infinity" Double/NEGATIVE_INFINITY + "1.7976931348623157E308" Double/MAX_VALUE + "4.9E-324" Double/MIN_VALUE) + (is (Double/isNaN (parse-double "NaN"))) + (are [s] ;; nil on invalid string + (nil? (parse-long s)) + "1.7976931348623157E309" ;; past max double + "9.9E-324")) ;; past min double + +;; generative test - gen double -> str -> parse, compare +(deftest test-gen-parse-double + (let [res (chk/quick-check + 100000 + (prop/for-all* [gen/double] + #(let [parsed (-> % str parse-double)] + (if (Double/isNaN %) + (Double/isNaN parsed) + (= % parsed)))))] + (if (:result res) + (is true) ;; pass + (is (:result res) (pr-str res))))) + +(deftest test-parse-uuid + (is (parse-uuid (.toString (UUID/randomUUID)))) + (is (nil? (parse-uuid "BOGUS"))) ;; nil on invalid uuid string + (are [s] ;; throw on invalid type (not string) + (try (parse-uuid s) (is false) (catch Throwable _ (is true))) + 123 + nil)) + +(deftest test-parse-boolean + (is (identical? true (parse-boolean "true"))) + (is (identical? false (parse-boolean "false"))) + + (are [s] ;; nil on invalid string + (nil? (parse-boolean s)) + "abc" + "TRUE" + "FALSE" + " true ") + + (are [s] ;; throw on invalid type (not string) + (try (parse-boolean s) (is false) (catch Throwable _ (is true))) + nil + false + true + 100)) \ No newline at end of file From f227b4b619e865b7cb853fe140d62f3f24994c0a Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Tue, 23 Nov 2021 12:20:05 -0600 Subject: [PATCH 25/78] CLJ-2668 Add NaN? and infinite? predicates Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 19 ++++++++++++++++++- test/clojure/test_clojure/predicates.clj | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 66e9f2655b..d4c677b541 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -8013,4 +8013,21 @@ fails, attempts to require sym's namespace and retries." "true" true "false" false nil) - (throw (IllegalArgumentException. (parsing-err s))))) \ No newline at end of file + (throw (IllegalArgumentException. (parsing-err s))))) + +(defn NaN? + {:doc "Returns true if num is NaN, else false" + :inline-arities #{1} + :inline (fn [num] `(Double/isNaN ~num)) + :added "1.11"} + + [^double num] + (Double/isNaN num)) + +(defn infinite? + {:doc "Returns true if num is negative or positive infinity, else false" + :inline-arities #{1} + :inline (fn [num] `(Double/isInfinite ~num)) + :added "1.11"} + [^double num] + (Double/isInfinite num)) diff --git a/test/clojure/test_clojure/predicates.clj b/test/clojure/test_clojure/predicates.clj index 7efdc6fe71..bb9074fb5f 100644 --- a/test/clojure/test_clojure/predicates.clj +++ b/test/clojure/test_clojure/predicates.clj @@ -172,3 +172,23 @@ (dotimes [i (count row)] (is (= ((resolve (nth preds i)) v) (nth row i)) (pr-str (list (nth preds i) v)))))))) + +;; Special double predicates + +(deftest test-double-preds + (is (NaN? ##NaN)) + (is (NaN? (Double/parseDouble "NaN"))) + (is (NaN? (Float/parseFloat "NaN"))) + (is (NaN? Float/NaN)) + (is (not (NaN? 5))) + (is (thrown? Throwable (NaN? nil))) + (is (thrown? Throwable (NaN? :xyz))) + + (is (infinite? ##Inf)) + (is (infinite? ##-Inf)) + (is (infinite? Double/POSITIVE_INFINITY)) + (is (infinite? Double/NEGATIVE_INFINITY)) + (is (infinite? Float/POSITIVE_INFINITY)) + (is (infinite? Float/NEGATIVE_INFINITY)) + (is (thrown? Throwable (infinite? nil))) + (is (thrown? Throwable (infinite? :xyz)))) \ No newline at end of file From 55c30c67b98bbf58b5589bbbd78fa236869f5b7d Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 16 Nov 2021 10:26:27 -0600 Subject: [PATCH 26/78] CLJ-1925: Adds implementation of random-uuid Signed-off-by: Alex Miller --- src/clj/clojure/core.clj | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index d4c677b541..a3a32522b4 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -6843,6 +6843,13 @@ fails, attempts to require sym's namespace and retries." {:added "1.9"} [x] (instance? java.util.UUID x)) +(defn random-uuid + {:doc "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). + + See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" + :added "1.11"} + ^java.util.UUID [] (java.util.UUID/randomUUID)) + (defn reduce "f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then From e3ee18f6bcab950ecf51fb33306f503971784c87 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Thu, 21 Oct 2021 22:50:46 -0500 Subject: [PATCH 27/78] CLJ-2664 Add clojure.java.math access to java.lang.Math Signed-off-by: Alex Miller --- build.xml | 1 + src/clj/clojure/java/math.clj | 556 ++++++++++++++++++++++++++++++++++ 2 files changed, 557 insertions(+) create mode 100644 src/clj/clojure/java/math.clj diff --git a/build.xml b/build.xml index 80c40f69de..444b5d9603 100644 --- a/build.xml +++ b/build.xml @@ -76,6 +76,7 @@ + diff --git a/src/clj/clojure/java/math.clj b/src/clj/clojure/java/math.clj new file mode 100644 index 0000000000..2d54fb52d7 --- /dev/null +++ b/src/clj/clojure/java/math.clj @@ -0,0 +1,556 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +; which can be found in the file epl-v10.html at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + +(ns + ^{:author "Alex Miller", + :doc "Clojure wrapper functions for java.lang.Math static methods. + + Function calls are inlined for performance, and type hinted for primitive + long or double parameters where appropriate. In general, Math methods are + optimized for performance and have bounds for error tolerance. If + greater precision is needed, use java.lang.StrictMath directly instead. + + For more complete information, see: + https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html"} + clojure.java.math + (:refer-clojure :exclude [min max])) + +(def + ^{:doc "Constant for e, the base for natural logarithms. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#E" + :added "1.11" + :const true + :tag 'double} + E + Math/E) + +(def + ^{:doc "Constant for pi, the ratio of the circumference of a circle to its diameter. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#PI" + :added "1.11" + :const true + :tag 'double} + PI + Math/PI) + +(defn sin + {:doc "Returns the sine of an angle. + If a is ##NaN, ##-Inf, ##Inf => ##NaN + If a is zero => zero with the same sign as a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sin-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/sin ~a)) + :added "1.11"} + ^double [^double a] + (Math/sin a)) + +(defn cos + {:doc "Returns the cosine of an angle. + If a is ##NaN, ##-Inf, ##Inf => ##NaN + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cos-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/cos ~a)) + :added "1.11"} + ^double [^double a] + (Math/cos a)) + +(defn tan + {:doc "Returns the tangent of an angle. + If a is ##NaN, ##-Inf, ##Inf => ##NaN + If a is zero => zero with the same sign as a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tan-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/tan ~a)) + :added "1.11"} + ^double [^double a] + (Math/tan a)) + +(defn asin + {:doc "Returns the arc sine of an angle, in the range -pi/2 to pi/2. + If a is ##NaN or |a|>1 => ##NaN + If a is zero => zero with the same sign as a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#asin-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/asin ~a)) + :added "1.11"} + ^double [^double a] + (Math/asin a)) + +(defn acos + {:doc "Returns the arc cosine of a, in the range 0.0 to pi. + If a is ##NaN or |a|>1 => ##NaN + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#acos-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/acos ~a)) + :added "1.11"} + ^double [^double a] + (Math/acos a)) + +(defn atan + {:doc "Returns the arc tangent of a, in the range of -pi/2 to pi/2. + If a is ##NaN => ##NaN + If a is zero => zero with the same sign as a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/atan ~a)) + :added "1.11"} + ^double [^double a] + (Math/atan a)) + +(defn to-radians + {:doc "Converts an angle in degrees to an approximate equivalent angle in radians. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toRadians-double-" + :inline-arities #{1} + :inline (fn [deg] `(Math/toRadians ~deg)) + :added "1.11"} + ^double [^double deg] + (Math/toRadians deg)) + +(defn to-degrees + {:doc "Converts an angle in radians to an approximate equivalent angle in degrees. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toDegrees-double-" + :inline-arities #{1} + :inline (fn [r] `(Math/toDegrees ~r)) + :added "1.11"} + ^double [^double r] + (Math/toDegrees r)) + +(defn exp + {:doc "Returns Euler's number e raised to the power of a. + If a is ##NaN => ##NaN + If a is ##Inf => ##Inf + If a is ##-Inf => +0.0 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#exp-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/exp ~a)) + :added "1.11"} + ^double [^double a] + (Math/exp a)) + +(defn log + {:doc "Returns the natural logarithm (base e) of a. + If a is ##NaN or negative => ##NaN + If a is ##Inf => ##Inf + If a is zero => ##-Inf + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/log ~a)) + :added "1.11"} + ^double [^double a] + (Math/log a)) + +(defn log10 + {:doc "Returns the logarithm (base 10) of a. + If a is ##NaN or negative => ##NaN + If a is ##Inf => ##Inf + If a is zero => ##-Inf + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log10-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/log10 ~a)) + :added "1.11"} + ^double [^double a] + (Math/log10 a)) + +(defn sqrt + {:doc "Returns the positive square root of a. + If a is ##NaN or negative => ##NaN + If a is ##Inf => ##Inf + If a is zero => a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sqrt-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/sqrt ~a)) + :added "1.11"} + ^double [^double a] + (Math/sqrt a)) + +(defn cbrt + {:doc "Returns the cube root of a. + If a is ##NaN => ##NaN + If a is ##Inf or ##-Inf => a + If a is zero => zero with sign matching a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cbrt-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/cbrt ~a)) + :added "1.11"} + ^double [^double a] + (Math/cbrt a)) + +(defn IEEE-remainder + {:doc "Returns the remainder per IEEE 754 such that + remainder = dividend - divisor * n + where n is the integer closest to the exact value of dividend / divisor. + If two integers are equally close, then n is the even one. + If the remainder is zero, sign will match dividend. + If dividend or divisor is ##NaN, or dividend is ##Inf or ##-Inf, or divisor is zero => ##NaN + If dividend is finite and divisor is infinite => dividend + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#IEEEremainder-double-double-" + :inline-arities #{2} + :inline (fn [dividend divisor] `(Math/IEEEremainder ~dividend ~divisor)) + :added "1.11"} + ^double [^double dividend ^double divisor] + (Math/IEEEremainder dividend divisor)) + +(defn ceil + {:doc "Returns the smallest double greater than or equal to a, and equal to a + mathematical integer. + If a is ##NaN or ##Inf or ##-Inf or already equal to an integer => a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ceil-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/ceil ~a)) + :added "1.11"} + ^double [^double a] + (Math/ceil a)) + +(defn floor + {:doc "Returns the largest double less than or equal to a, and equal to a + mathematical integer. + If a is ##NaN or ##Inf or ##-Inf or already equal to an integer => a + If a is less than zero but greater than -1.0 => -0.0 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floor-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/floor ~a)) + :added "1.11"} + ^double [^double a] + (Math/floor a)) + +(defn rint + {:doc "Returns the double closest to a and equal to a mathematical integer. + If two values are equally close, return the even one. + If a is ##NaN or ##Inf or ##-Inf or zero => a + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#rint-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/rint ~a)) + :added "1.11"} + ^double [^double a] + (Math/rint a)) + +(defn atan2 + {:doc "Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta). + Computes the phase theta by computing an arc tangent of y/x in the range of -pi to pi. + For more details on special cases, see: + https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan2-double-double-" + :inline-arities #{2} + :inline (fn [y x] `(Math/atan2 ~y ~x)) + :added "1.11"} + ^double [^double y ^double x] + (Math/atan2 y x)) + +(defn pow + {:doc "Returns the value of a raised to the power of b. + For more details on special cases, see: + https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#pow-double-double-" + :inline-arities #{2} + :inline (fn [a b] `(Math/pow ~a ~b)) + :added "1.11"} + ^double [^double a ^double b] + (Math/pow a b)) + +(defn round + {:doc "Returns the closest long to a. If equally close to two values, return the one + closer to ##Inf. + If a is ##NaN => 0 + If a is ##-Inf or < Long/MIN_VALUE => Long/MIN_VALUE + If a is ##Inf or > Long/MAX_VALUE => Long/MAX_VALUE + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#round-double-" + :inline-arities #{1} + :inline (fn [a] `(Math/round ~a)) + :added "1.11"} + ^long [^double a] + (Math/round a)) + +(defn random + {:doc "Returns a positive double between 0.0 and 1.0, chosen pseudorandomly with + approximately random distribution. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#random--" + :inline-arities #{0} + :inline (fn [] `(Math/random)) + :added "1.11"} + ^double [] + (Math/random)) + +(defn add-exact + {:doc "Returns the sum of x and y, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#addExact-long-long-" + :inline-arities #{2} + :inline (fn [x y] `(Math/addExact ~x ~y)) + :added "1.11"} + ^long [^long x ^long y] + (Math/addExact x y)) + +(defn subtract-exact + {:doc "Returns the difference of x and y, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#subtractExact-long-long-" + :inline-arities #{2} + :inline (fn [x y] `(Math/subtractExact ~x ~y)) + :added "1.11"} + ^long [^long x ^long y] + (Math/subtractExact x y)) + +(defn multiply-exact + {:doc "Returns the product of x and y, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#multiplyExact-long-long-" + :inline-arities #{2} + :inline (fn [x y] `(Math/multiplyExact ~x ~y)) + :added "1.11"} + ^long [^long x ^long y] + (Math/multiplyExact x y)) + +(defn increment-exact + {:doc "Returns a incremented by 1, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#incrementExact-long-" + :inline-arities #{1} + :inline (fn [a] `(Math/incrementExact ~a)) + :added "1.11"} + ^long [^long a] + (Math/incrementExact a)) + +(defn decrement-exact + {:doc "Returns a decremented by 1, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#decrementExact-long-" + :inline-arities #{1} + :inline (fn [a] `(Math/decrementExact ~a)) + :added "1.11"} + ^long [^long a] + (Math/decrementExact a)) + +(defn negative-exact + {:doc "Returns the negation of a, throws ArithmeticException on overflow. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#negateExact-long-" + :inline-arities #{1} + :inline (fn [a] `(Math/negateExact ~a)) + :added "1.11"} + ^long [^long a] + (Math/negateExact a)) + +(defn floor-div + {:doc "Integer division that rounds to negative infinity (as opposed to zero). + The special case (floorDiv Long/MIN_VALUE -1) overflows and returns Long/MIN_VALUE. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorDiv-long-long-" + :inline-arities #{2} + :inline (fn [x y] `(Math/floorDiv ~x ~y)) + :added "1.11"} + ^long [^long x ^long y] + (Math/floorDiv x y)) + +(defn floor-mod + {:doc "Integer modulus x - (floorDiv(x, y) * y). Sign matches y and is in the + range -|y| < r < |y|. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorMod-long-long-" + :inline-arities #{2} + :inline (fn [x y] `(Math/floorMod ~x ~y)) + :added "1.11"} + ^long [^long x ^long y] + (Math/floorMod x y)) + +(defn abs + {:doc "Returns the absolute value of a (long or double). + If not negative, a is returned, else negation of a is returned. + If a is Long/MIN_VALUE => Long/MIN_VALUE + If a is a double and zero => +0.0 + If a is a double and ##Inf or ##-Inf => ##Inf + If a is a double and ##NaN => ##NaN + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#abs-long-" + :inline-arities #{1} + :inline (fn [a] `(Math/abs ~a)) + :added "1.11"} + [a] + (Math/abs a)) + +(defn max + {:doc "Returns the greater of a or b. + If doubles and a or b is ##NaN => ##NaN + If doubles and one is negative zero, other positive zero => positive zero + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#max-long-long-" + :inline-arities #{2} + :inline (fn [a b] `(Math/max ~a ~b)) + :added "1.11"} + [a b] + (Math/max a b)) + +(defn min + {:doc "Returns the lesser of a or b. + If doubles and a or b is ##NaN => ##NaN + If doubles and one is negative zero, other positive zero => negative zero + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#min-double-double-" + :inline-arities #{2} + :inline (fn [p0 p1] `(Math/min ~p0 ~p1)) + :added "1.11"} + [p0 p1] + (Math/min p0 p1)) + +(defn ulp + {:doc "Returns the size of an ulp (unit in last place) for d. + If d is ##NaN => ##NaN + If d is ##Inf or ##-Inf => ##Inf + If d is zero => Double/MIN_VALUE + If d is +/- Double/MAX_VALUE => 2^971 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ulp-double-" + :inline-arities #{1} + :inline (fn [d] `(Math/ulp ~d)) + :added "1.11"} + ^double [^double d] + (Math/ulp d)) + +(defn signum + {:doc "Returns the signum function of d - zero for zero, 1.0 if >0, -1.0 if <0. + If d is ##NaN => ##NaN + If d is ##Inf or ##-Inf => d + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#signum-double-" + :inline-arities #{1} + :inline (fn [d] `(Math/signum ~d)) + :added "1.11"} + ^double [^double d] + (Math/signum d)) + +(defn sinh + {:doc "Returns the hyperbolic sine of x, (e^x - e^-x)/2. + If x is ##NaN => ##NaN + If x is ##Inf or ##-Inf or zero => x + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sinh-double-" + :inline-arities #{1} + :inline (fn [x] `(Math/sinh ~x)) + :added "1.11"} + ^double [^double x] + (Math/sinh x)) + +(defn cosh + {:doc "Returns the hyperbolic cosine of x, (e^x + e^-x)/2. + If x is ##NaN => ##NaN + If x is ##Inf or ##-Inf => ##Inf + If x is zero => 1.0 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cosh-double-" + :inline-arities #{1} + :inline (fn [x] `(Math/cosh ~x)) + :added "1.11"} + ^double [^double x] + (Math/cosh x)) + +(defn tanh + {:doc "Returns the hyperbolic tangent of x, sinh(x)/cosh(x). + If x is ##NaN => ##NaN + If x is zero => zero, with same sign + If x is ##Inf => +1.0 + If x is ##-Inf => -1.0 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tanh-double-" + :inline-arities #{1} + :inline (fn [x] `(Math/tanh ~x)) + :added "1.11"} + ^double [^double x] + (Math/tanh x)) + +(defn hypot + {:doc "Returns sqrt(x^2 + y^2) without intermediate underflow or overflow. + If x or y is ##Inf or ##-Inf => ##Inf + If x or y is ##NaN and neither is ##Inf or ##-Inf => ##NaN + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#hypot-double-double-" + :inline-arities #{2} + :inline (fn [x y] `(Math/hypot ~x ~y)) + :added "1.11"} + ^double [^double x ^double y] + (Math/hypot x y)) + +(defn expm1 + {:doc "Returns e^x - 1. Near 0, expm1(x)+1 is more accurate to e^x than exp(x). + If x is ##NaN => ##NaN + If x is ##Inf => #Inf + If x is ##-Inf => -1.0 + If x is zero => x + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#expm1-double-" + :inline-arities #{1} + :inline (fn [x] `(Math/expm1 ~x)) + :added "1.11"} + ^double [^double x] + (Math/expm1 x)) + +(defn log1p + {:doc "Returns ln(1+x). For small values of x, log1p(x) is more accurate than + log(1.0+x). + If x is ##NaN or < -1 => ##NaN + If x is ##Inf or ##-Inf or x => x + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log1p-double-" + :inline-arities #{1} + :inline (fn [x] `(Math/log1p ~x)) + :added "1.11"} + ^double [^double x] + (Math/log1p x)) + +(defn copy-sign + {:doc "Returns a double with the magnitude of the first argument and the sign of + the second. + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#copySign-double-double-" + :inline-arities #{2} + :inline (fn [magnitude sign] `(Math/copySign ~magnitude ~sign)) + :added "1.11"} + ^double [^double magnitude ^double sign] + (Math/copySign magnitude sign)) + +(defn get-exponent + {:doc "Returns the exponent of d. + If d is ##NaN, ##Inf, ##-Inf => Double/MAX_EXPONENT + 1 + If d is zero or subnormal => Double/MIN_EXPONENT - 1 + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#getExponent-double-" + :inline-arities #{1} + :inline (fn [d] `(Math/getExponent ~d)) + :added "1.11"} + [^double d] + (Math/getExponent d)) + +(defn next-after + {:doc "Returns the adjacent floating point number to start in the direction of + the second argument. If the arguments are equal, the second is returned. + If either arg is #NaN => #NaN + If both arguments are signed zeros => direction + If start is +-Double/MIN_VALUE and direction would cause a smaller magnitude + => zero with sign matching start + If start is ##Inf or ##-Inf and direction would cause a smaller magnitude + => Double/MAX_VALUE with same sign as start + If start is equal to +=Double/MAX_VALUE and direction would cause a larger magnitude + => ##Inf or ##-Inf with sign matching start + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextAfter-double-double-" + :inline-arities #{2} + :inline (fn [start direction] `(Math/nextAfter ~start ~direction)) + :added "1.11"} + ^double [^double start ^double direction] + (Math/nextAfter start direction)) + +(defn next-up + {:doc "Returns the adjacent double of d in the direction of ##Inf. + If d is ##NaN => ##NaN + If d is ##Inf => ##Inf + If d is zero => Double/MIN_VALUE + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextUp-double-" + :inline-arities #{1} + :inline (fn [d] `(Math/nextUp ~d)) + :added "1.11"} + ^double [^double d] + (Math/nextUp d)) + +(defn next-down + {:doc "Returns the adjacent double of d in the direction of ##-Inf. + If d is ##NaN => ##NaN + If d is ##Inf => ##-Inf + If d is zero => Double/MIN_VALUE + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-" + :inline-arities #{1} + :inline (fn [d] `(Math/nextDown ~d)) + :added "1.11"} + ^double [^double d] + (Math/nextDown d)) + +(defn scalb + {:doc "Returns d * 2^scaleFactor, scaling by a factor of 2. If the exponent + is between Double/MIN_EXPONENT and Double/MAX_EXPONENT, the answer is exact. + If d is ##NaN => ##NaN + If d is ##Inf or ##-Inf => ##Inf or ##-Inf respectively + If d is zero => zero of same sign as d + See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-" + :inline-arities #{1} + :inline (fn [d scaleFactor] `(Math/scalb ~d ~scaleFactor)) + :added "1.11"} + ^double [^double d scaleFactor] + (Math/scalb d scaleFactor)) \ No newline at end of file From 3c9a245e1c6ee3dfe55822b5828427c32d9901d0 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Wed, 27 Oct 2021 14:17:09 -0500 Subject: [PATCH 28/78] CLJ-2666 Make javadoc text match example Signed-off-by: Alex Miller --- src/jvm/clojure/java/api/Clojure.java | 2 +- src/jvm/clojure/java/api/package.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jvm/clojure/java/api/Clojure.java b/src/jvm/clojure/java/api/Clojure.java index 3667b22791..8a9ef9b543 100644 --- a/src/jvm/clojure/java/api/Clojure.java +++ b/src/jvm/clojure/java/api/Clojure.java @@ -41,7 +41,7 @@ * require.invoke(Clojure.read("clojure.set")); * *

IFns can be passed to higher order functions, e.g. the - * example below passes plus to read:

+ * example below passes inc to map:

* *
  * IFn map = Clojure.var("clojure.core", "map");
diff --git a/src/jvm/clojure/java/api/package.html b/src/jvm/clojure/java/api/package.html
index 6536c33ab5..a24d3c9b79 100644
--- a/src/jvm/clojure/java/api/package.html
+++ b/src/jvm/clojure/java/api/package.html
@@ -57,7 +57,7 @@
 

IFns can be passed to higher order functions, e.g. the - example below passes plus to read: + example below passes inc to map:

 IFn map = Clojure.var("clojure.core", "map");
 IFn inc = Clojure.var("clojure.core", "inc");

From ade22645ba5dbf4c0d8115b19938af96d6fb4cd5 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 18 Nov 2021 09:47:56 -0600
Subject: [PATCH 29/78] CLJ-1360 Update clojure.string/split docstring
 regarding trailing empty parts

Signed-off-by: Alex Miller 
---
 src/clj/clojure/string.clj | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/string.clj b/src/clj/clojure/string.clj
index 35e0650f65..38f0d6d91d 100644
--- a/src/clj/clojure/string.clj
+++ b/src/clj/clojure/string.clj
@@ -218,7 +218,8 @@ Design notes for clojure.string:
 
 (defn split
   "Splits string on a regular expression.  Optional argument limit is
-  the maximum number of splits. Not lazy. Returns vector of the splits."
+  the maximum number of parts. Not lazy. Returns vector of the parts.
+  Trailing empty strings are not returned - pass limit of -1 to return all."
   {:added "1.2"}
   ([^CharSequence s ^Pattern re]
      (LazilyPersistentVector/createOwning (.split re s)))
@@ -226,7 +227,7 @@ Design notes for clojure.string:
      (LazilyPersistentVector/createOwning (.split re s limit))))
 
 (defn split-lines
-  "Splits s on \\n or \\r\\n."
+  "Splits s on \\n or \\r\\n. Trailing empty lines are not returned."
   {:added "1.2"}
   [^CharSequence s]
   (split s #"\r?\n"))

From 554090e7fd5f33fc3c1c962bb34af53a01332a75 Mon Sep 17 00:00:00 2001
From: Arne Brasseur 
Date: Thu, 18 Nov 2021 09:41:29 -0600
Subject: [PATCH 30/78] CLJ-2249 Clarify clojure.core/get docstring regarding
 sets, strings, arrays, ILookup

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index a3a32522b4..9f3cdf371f 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1494,7 +1494,8 @@
   [coll key] (. clojure.lang.RT (contains coll key)))
 
 (defn get
-  "Returns the value mapped to key, not-found or nil if key not present."
+  "Returns the value mapped to key, not-found or nil if key not present
+  in associative collection, set, string, array, or ILookup instance."
   {:inline (fn  [m k & nf] `(. clojure.lang.RT (get ~m ~k ~@nf)))
    :inline-arities #{2 3}
    :added "1.0"}

From e1220832d900745727cf5a1b69f4a6cd664f1443 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 5 Oct 2021 10:32:45 -0500
Subject: [PATCH 31/78] CLJ-2488 Add definition to reify docstring

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core_deftype.clj | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 786f0d4b53..7906ccbe35 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -67,8 +67,9 @@
       (throw (IllegalArgumentException. (apply print-str "Unsupported option(s) -" bad-opts))))
     [interfaces methods opts]))
 
-(defmacro reify 
-  "reify is a macro with the following structure:
+(defmacro reify
+  "reify creates an object implementing a protocol or interface.
+  reify is a macro with the following structure:
 
  (reify options* specs*)
   

From 631c46ed98ed3bfefdb8a15080e004ab470b0bf4 Mon Sep 17 00:00:00 2001
From: Nikita Prokopov 
Date: Sun, 30 Aug 2015 18:56:04 +0600
Subject: [PATCH 32/78] CLJ-1808 map-invert should use reduce-kv and transient

Signed-off-by: Alex Miller 
---
 src/clj/clojure/set.clj | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/clj/clojure/set.clj b/src/clj/clojure/set.clj
index b63a004475..9ffb72900a 100644
--- a/src/clj/clojure/set.clj
+++ b/src/clj/clojure/set.clj
@@ -106,7 +106,11 @@
 (defn map-invert
   "Returns the map with the vals mapped to the keys."
   {:added "1.0"}
-  [m] (reduce (fn [m [k v]] (assoc m v k)) {} m))
+  [m]
+  (persistent!
+    (reduce-kv (fn [m k v] (assoc! m v k))
+               (transient {})
+               m)))
 
 (defn join
   "When passed 2 rels, returns the rel corresponding to the natural

From d004e799364e29815dc1b080dbf9e8bd9858c321 Mon Sep 17 00:00:00 2001
From: Steve Miner 
Date: Tue, 5 Oct 2021 09:48:39 -0500
Subject: [PATCH 33/78] CLJ-2065 Support IKVReduce on SubVector

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/APersistentVector.java | 12 +++++++++++-
 test/clojure/test_clojure/vectors.clj       |  4 ++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/jvm/clojure/lang/APersistentVector.java b/src/jvm/clojure/lang/APersistentVector.java
index c9f15cdd3f..de8a09ea68 100644
--- a/src/jvm/clojure/lang/APersistentVector.java
+++ b/src/jvm/clojure/lang/APersistentVector.java
@@ -544,7 +544,7 @@ public APersistentVector.RSeq withMeta(IPersistentMap meta){
 	}
 }
 
-public static class SubVector extends APersistentVector implements IObj{
+public static class SubVector extends APersistentVector implements IObj, IKVReduce{
 	public final IPersistentVector v;
 	public final int start;
 	public final int end;
@@ -574,6 +574,16 @@ public Iterator iterator(){
 		return super.iterator();
 	}
 
+	public Object kvreduce(IFn f, Object init){
+		int cnt = count();
+		for (int i=0; i= end) || (i < 0))
 			throw new IndexOutOfBoundsException();
diff --git a/test/clojure/test_clojure/vectors.clj b/test/clojure/test_clojure/vectors.clj
index 0bea3ff4b8..0be0bf14e8 100644
--- a/test/clojure/test_clojure/vectors.clj
+++ b/test/clojure/test_clojure/vectors.clj
@@ -416,3 +416,7 @@
   (is (= [0 1 2 3] (vec (reify clojure.lang.IReduceInit
                           (reduce [_ f start]
                             (reduce f start (range 4))))))))
+
+(deftest test-reduce-kv-vectors
+  (is (= 25 (reduce-kv + 10 [2 4 6])))
+  (is (= 25 (reduce-kv + 10 (subvec [0 2 4 6] 1)))))

From e21bbfe1d1b06ae703e939951e6c8f199969d70b Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 23 Nov 2021 12:47:24 -0600
Subject: [PATCH 34/78] CLJ-2326 Add :direct-linking to *compiler-options*
 docstring and remove Alpha marking

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 9f3cdf371f..0dba6fcd97 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -6473,7 +6473,10 @@ fails, attempts to require sym's namespace and retries."
   Supported options:
   :elide-meta - a collection of metadata keys to elide during compilation.
   :disable-locals-clearing - set to true to disable clearing, useful for using a debugger
-  Alpha, subject to change."
+  :direct-linking - set to true to use direct static invocation of functions, rather than vars
+    Note that call sites compiled with direct linking will not be affected by var redefinition.
+    Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition.
+  See https://clojure.org/reference/compilation for more information."
   {:added "1.4"})
 
 (add-doc-and-meta *ns*

From 8ebad0ab3f912932d94874120cad89493f2aa22e Mon Sep 17 00:00:00 2001
From: "Hudson @ build.clojure.org" 
Date: Tue, 23 Nov 2021 13:25:56 -0600
Subject: [PATCH 35/78] [maven-release-plugin] prepare release
 clojure-1.11.0-alpha3

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 71c4378068..d9ae7e5f14 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-master-SNAPSHOT
+  1.11.0-alpha3
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.0-alpha3
   
 
   

From 7697d5da77a319077e71343f76fa204327881de4 Mon Sep 17 00:00:00 2001
From: "Hudson @ build.clojure.org" 
Date: Tue, 23 Nov 2021 13:25:56 -0600
Subject: [PATCH 36/78] [maven-release-plugin] prepare for next development
 iteration

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index d9ae7e5f14..71c4378068 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-alpha3
+  1.11.0-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.0-alpha3
+    HEAD
   
 
   

From abe19832c0294fec4c9c55430c9262c4b6d2f8b1 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 30 Nov 2021 10:45:25 -0600
Subject: [PATCH 37/78] Remove/ignore project files

---
 .gitignore                                    |  1 +
 ...ven__org_clojure_data_generators_0_1_2.xml | 13 -----------
 ...ven__org_clojure_test_generative_0_4_0.xml | 13 -----------
 clojure.iml                                   | 23 -------------------
 4 files changed, 1 insertion(+), 49 deletions(-)
 delete mode 100644 .idea/libraries/Maven__org_clojure_data_generators_0_1_2.xml
 delete mode 100644 .idea/libraries/Maven__org_clojure_test_generative_0_4_0.xml
 delete mode 100644 clojure.iml

diff --git a/.gitignore b/.gitignore
index 5376efaf3f..18cf4cc05c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ nbproject/private/
 maven-classpath
 maven-classpath.properties
 .idea/
+*.iml
diff --git a/.idea/libraries/Maven__org_clojure_data_generators_0_1_2.xml b/.idea/libraries/Maven__org_clojure_data_generators_0_1_2.xml
deleted file mode 100644
index 78f485eeb9..0000000000
--- a/.idea/libraries/Maven__org_clojure_data_generators_0_1_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-  
-    
-      
-    
-    
-      
-    
-    
-      
-    
-  
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_clojure_test_generative_0_4_0.xml b/.idea/libraries/Maven__org_clojure_test_generative_0_4_0.xml
deleted file mode 100644
index 78fac6dfd0..0000000000
--- a/.idea/libraries/Maven__org_clojure_test_generative_0_4_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-  
-    
-      
-    
-    
-      
-    
-    
-      
-    
-  
-
\ No newline at end of file
diff --git a/clojure.iml b/clojure.iml
deleted file mode 100644
index c1c8a6a84a..0000000000
--- a/clojure.iml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-  
-    
-    
-    
-      
-      
-      
-      
-      
-      
-      
-    
-    
-    
-    
-    
-    
-    
-    
-  
-
\ No newline at end of file

From f5e5a4a7b8e0785436f0bbb9b91b6de9f754aa33 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 13 Jan 2022 11:57:31 -0600
Subject: [PATCH 38/78] CLJ-2684 Update contrib deps

Signed-off-by: Alex Miller 
---
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pom.xml b/pom.xml
index 71c4378068..59159805a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,7 +41,7 @@
     
       org.clojure
       spec.alpha
-       0.3.214
+       0.3.218
     
     
       org.clojure
@@ -51,7 +51,7 @@
     
       org.clojure
       test.generative
-      0.5.2
+      1.0.0
       test
       
         
@@ -63,7 +63,7 @@
     
       org.clojure
       test.check
-      0.9.0
+      1.1.1
       test
       
         

From b32e35ae89d291882dbdb662c4193ecfa9a593e8 Mon Sep 17 00:00:00 2001
From: Alexander Yakushev 
Date: Thu, 13 Jan 2022 11:29:09 -0600
Subject: [PATCH 39/78] CLJ-2621: Make InstanceMethodExpr.emit discard unused
 primitive returns without boxing

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/Compiler.java         | 16 ++++++++++++----
 test/clojure/test_clojure/java_interop.clj | 18 +++++++++++++++++-
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 041786e888..ce16f85a21 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -1612,8 +1612,16 @@ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
 				gen.invokeInterface(type, m);
 			else
 				gen.invokeVirtual(type, m);
-			//if(context != C.STATEMENT || method.getReturnType() == Void.TYPE)
-			HostExpr.emitBoxReturn(objx, gen, method.getReturnType());
+			Class retClass = method.getReturnType();
+			if(context == C.STATEMENT)
+				{
+				if(retClass == long.class || retClass == double.class)
+					gen.pop2();
+				else if(retClass != void.class)
+					gen.pop();
+				}
+			else
+				HostExpr.emitBoxReturn(objx, gen, retClass);
 			}
 		else
 			{
@@ -1627,9 +1635,9 @@ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
 				method.emitClearLocals(gen);
 				}
 			gen.invokeStatic(REFLECTOR_TYPE, invokeInstanceMethodMethod);
+			if(context == C.STATEMENT)
+				gen.pop();
 			}
-		if(context == C.STATEMENT)
-			gen.pop();
 	}
 
 	public boolean hasJavaClass(){
diff --git a/test/clojure/test_clojure/java_interop.clj b/test/clojure/test_clojure/java_interop.clj
index 30fab56e56..cb21064b25 100644
--- a/test/clojure/test_clojure/java_interop.clj
+++ b/test/clojure/test_clojure/java_interop.clj
@@ -13,7 +13,8 @@
   (:use clojure.test)
   (:require [clojure.inspector]
             [clojure.set :as set])
-  (:import java.util.Base64))
+  (:import java.util.Base64
+           (java.util.concurrent.atomic AtomicLong AtomicInteger)))
 
 ; http://clojure.org/java_interop
 ; http://clojure.org/compilation
@@ -589,3 +590,18 @@
   (is (= (char \a) \a)))
 
 ;; Note: More coercions in numbers.clj
+
+; Test that primitive boxing elision in statement context works
+; correctly (CLJ-2621)
+
+(defn inc-atomic-int [^AtomicInteger l]
+  (.incrementAndGet l)
+  nil)
+
+(defn inc-atomic-long [^AtomicLong l]
+  (.incrementAndGet l)
+  nil)
+
+(deftest test-boxing-prevention-when-compiling-statements
+  (is (= 1 (.get (doto (AtomicInteger. 0) inc-atomic-int))))
+  (is (= 1 (.get (doto (AtomicLong. 0) inc-atomic-long)))))

From b30a99014814f2fe68833622a567c80133b0c417 Mon Sep 17 00:00:00 2001
From: Fogus 
Date: Thu, 13 Jan 2022 11:37:08 -0500
Subject: [PATCH 40/78] CLJ-2663: Added a guard in APVector#doEquiv so that
 List operands that do not respond to #size are not checked. Also, added count
 short-circuit logic to ASeq#equiv in an attempt to leverage fast-count
 benefit, but the guard is more strict such that this and the operand should
 bouth be Counted.

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/APersistentVector.java | 13 ++++++++-----
 src/jvm/clojure/lang/ASeq.java              |  5 +++++
 test/clojure/test_clojure/vectors.clj       |  8 ++++++++
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/jvm/clojure/lang/APersistentVector.java b/src/jvm/clojure/lang/APersistentVector.java
index de8a09ea68..3e88d14dbf 100644
--- a/src/jvm/clojure/lang/APersistentVector.java
+++ b/src/jvm/clojure/lang/APersistentVector.java
@@ -98,15 +98,18 @@ static boolean doEquiv(IPersistentVector v, Object obj){
 	else if(obj instanceof List)
 		{
 		Collection ma = (Collection) obj;
-		if(ma.size() != v.count())
+
+		if((!(ma instanceof IPersistentCollection) || (ma instanceof Counted)) && (ma.size() != v.count()))
 			return false;
-		for(Iterator i1 = ((List) v).iterator(), i2 = ma.iterator();
-		    i1.hasNext();)
+
+		Iterator i2 = ma.iterator();
+
+		for(Iterator i1 = ((List) v).iterator(); i1.hasNext();)
 			{
-			if(!Util.equiv(i1.next(), i2.next()))
+			if(!i2.hasNext() || !Util.equiv(i1.next(), i2.next()))
 				return false;
 			}
-		return true;
+		return !i2.hasNext();
 		}
 	else
 		{
diff --git a/src/jvm/clojure/lang/ASeq.java b/src/jvm/clojure/lang/ASeq.java
index 325aa27c24..f0f8e5d447 100644
--- a/src/jvm/clojure/lang/ASeq.java
+++ b/src/jvm/clojure/lang/ASeq.java
@@ -37,6 +37,11 @@ public boolean equiv(Object obj){
 
 	if(!(obj instanceof Sequential || obj instanceof List))
 		return false;
+
+	if(this instanceof Counted && obj instanceof Counted &&
+	   ((Counted)this).count() != ((Counted)obj).count())
+		return false;
+
 	ISeq ms = RT.seq(obj);
 	for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next())
 		{
diff --git a/test/clojure/test_clojure/vectors.clj b/test/clojure/test_clojure/vectors.clj
index 0be0bf14e8..ea2b8e77d5 100644
--- a/test/clojure/test_clojure/vectors.clj
+++ b/test/clojure/test_clojure/vectors.clj
@@ -420,3 +420,11 @@
 (deftest test-reduce-kv-vectors
   (is (= 25 (reduce-kv + 10 [2 4 6])))
   (is (= 25 (reduce-kv + 10 (subvec [0 2 4 6] 1)))))
+
+(deftest test-vector-eqv-to-non-counted-types
+  (is (not= (range) [0 1 2]))
+  (is (not= [0 1 2] (range)))
+  (is (= [0 1 2] (take 3 (range))))
+  (is (= [0 1 2] (new java.util.ArrayList [0 1 2])))
+  (is (not= [1 2] (take 1 (cycle [1 2]))))
+  (is (= [1 2 3 nil 4 5 6 nil] (eduction cat [[1 2 3 nil] [4 5 6 nil]]))))

From 304d7c6a81bd7d8511e9ef3d89dc199b1464afaa Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Wed, 12 Jan 2022 16:03:23 -0600
Subject: [PATCH 41/78] CLJ-2677 In clojure.math inline methods, use coercion
 functions to resolve to single overload

Signed-off-by: Alex Miller 
---
 build.xml                           |   2 +-
 codegen/gen_math.clj                | 263 +++++++++++++++++++++++
 src/clj/clojure/{java => }/math.clj | 141 +++++-------
 test/clojure/test_clojure/math.clj  | 320 ++++++++++++++++++++++++++++
 4 files changed, 638 insertions(+), 88 deletions(-)
 create mode 100644 codegen/gen_math.clj
 rename src/clj/clojure/{java => }/math.clj (83%)
 create mode 100644 test/clojure/test_clojure/math.clj

diff --git a/build.xml b/build.xml
index 444b5d9603..6796b3d986 100644
--- a/build.xml
+++ b/build.xml
@@ -76,7 +76,6 @@
       
       
       
-      
       
       
       
@@ -86,6 +85,7 @@
       
       
       
+      
     
   
 
diff --git a/codegen/gen_math.clj b/codegen/gen_math.clj
new file mode 100644
index 0000000000..484649d3d3
--- /dev/null
+++ b/codegen/gen_math.clj
@@ -0,0 +1,263 @@
+;; This code was used to generate the clojure.math namespace in
+;; Clojure 1.11 to wrap Java 1.8 java.lang.Math methods. There are
+;; many small tweaks in this to get exactly the output that was
+;; desired and it was not intended to be reused in any way, it is
+;; included here for future reference.
+
+(ns gen-math
+  (:require
+    [clojure.reflect :as reflect]
+    [clojure.set :as set]
+    [clojure.string :as str])
+  (:import
+    [java.io StringWriter Writer]))
+
+;; manually created
+(declare HEADER)
+(declare FNS)
+(declare DOCS)
+(declare ARGS)
+(declare ARGTYPES)
+
+(def const-template
+  "(def
+  ^{:doc %s
+    :added %s
+    :const true
+    :tag %s}
+  %s
+  %s)\n\n")
+
+(defn- emit-constant
+  [^Writer writer {:keys [cname name added type]}]
+  (let [sym (symbol (str cname) (str name))
+        doc (str "\"" (get DOCS (symbol name)) "\"")
+        tag (str "'" type)]
+    (.write writer
+      (format const-template doc (pr-str added) tag name sym))))
+
+(def fn-template
+  "(defn %s
+  {:doc %s
+   :inline-arities %s
+   :inline %s
+   :added %s}
+  %s%s
+  %s)\n\n")
+
+(defn- clojurize
+  [sym]
+  (or
+    (get '{IEEEremainder IEEE-remainder} sym)
+    (let [s (name sym)]
+      (symbol
+        (str
+          (reduce
+            (fn [^StringBuilder b ^Character c]
+              (if (Character/isUpperCase c)
+                (.. b (append "-") (append (Character/toLowerCase c)))
+                (.append b c)))
+            (StringBuilder.)
+            s))))))
+
+(defn- inline-body
+  [params param-types]
+  (str/join " "
+    (map (fn [p pt] (format "(%s ~%s)" pt p))
+      params param-types)))
+
+(defn- body
+  [params param-types on-types]
+  (map (fn [p pt] (if (contains? on-types pt) `(~pt ~p) p))
+    params param-types))
+
+(defn- emit-fn
+  [^Writer writer {:keys [cname fname sigs]}]
+  (let [sym (symbol (str cname) (str fname))
+        arities (group-by #(-> % :parameter-types count) sigs)
+        arity (-> arities keys first) ;; NOTE: ignore multiple arities, none in Math
+        arity-sigs (get arities arity)
+        cname (clojurize fname)
+        doc (str "\"" (get DOCS cname) "\"")
+        sig (if (= 1 (count arity-sigs)) (first arity-sigs) (get ARGTYPES cname))
+        {pts :parameter-types, rt :return-type} sig
+        ps (get ARGS cname)
+        ;; coerce all args in inline body
+        inline-body (format "(fn %s `(%s%s))" (pr-str ps) (if (< 0 (count ps)) (str sym " ") sym) (inline-body ps pts))
+        ;; ps are hinted, so coerce only ps that can't be hinted - int type
+        body `(~sym ~@(body ps pts #{'int}))
+        rts (if (#{'long 'double} rt) (str "^" rt " ") "")
+        hints (map #(if (#{'long 'double} %) (symbol (str "^" %)) nil) pts)
+        pst (vec (remove nil? (interleave hints ps)))]
+    (.write writer
+      (format fn-template cname doc #{arity} inline-body (pr-str "1.11") rts pst body))))
+
+(defn gen-static-wrappers
+  [csym]
+  (let [added "1.11"
+        members (:members (reflect/type-reflect (resolve csym)))
+        statics (filter #(set/subset? #{:public :static} (:flags %)) members)
+        {fs false, ms true} (group-by #(contains? % :return-type) statics)
+        methods (->> ms (filter (fn [m]
+                                  (or (= 'scalb (:name m))
+                                    (empty? (set/intersection #{'int 'float} (set (:parameter-types m))))))))
+        by-name (group-by :name methods)
+        writer (StringWriter.)]
+    (.write writer HEADER)
+    (doseq [f fs]
+      (emit-constant writer (merge f {:cname csym, :added added})))
+    (doseq [n FNS]
+      (emit-fn writer {:cname csym, :fname n, :added added, :sigs (get by-name n)}))
+    (spit "src/clj/clojure/math.clj" (str writer))))
+
+(comment
+  (gen-static-wrappers 'Math)
+  )
+
+;;;; Manually provided info used during the generator
+
+(def ^String HEADER
+  ";   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+(ns
+  ^{:author \"Alex Miller\",
+    :doc \"Clojure wrapper functions for java.lang.Math static methods.
+
+  Function calls are inlined for performance, and type hinted for primitive
+  long or double parameters where appropriate. In general, Math methods are
+  optimized for performance and have bounds for error tolerance. If
+  greater precision is needed, use java.lang.StrictMath directly instead.
+
+  For more complete information, see:
+  https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html\"}
+  clojure.math)
+
+(set! *warn-on-reflection* true)
+
+")
+
+;; fns
+
+;; omitted: toIntExact
+;; omitted but include in core w/polymorphic impl: abs, min, max
+(def FNS
+  '[sin cos tan asin acos atan toRadians toDegrees exp log log10
+    sqrt cbrt IEEEremainder ceil floor rint atan2 pow round random
+    addExact subtractExact multiplyExact incrementExact decrementExact negateExact
+    floorDiv floorMod ulp signum sinh cosh tanh hypot expm1 log1p copySign getExponent
+    nextAfter nextUp nextDown scalb])
+
+;; docstrings to use
+(def DOCS
+  '{
+    E "Constant for e, the base for natural logarithms.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#E"
+    PI "Constant for pi, the ratio of the circumference of a circle to its diameter.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#PI"
+    sin "Returns the sine of an angle.\n  If a is ##NaN, ##-Inf, ##Inf => ##NaN\n  If a is zero => zero with the same sign as a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sin-double-"
+    cos "Returns the cosine of an angle.\n  If a is ##NaN, ##-Inf, ##Inf => ##NaN\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cos-double-"
+    tan "Returns the tangent of an angle.\n  If a is ##NaN, ##-Inf, ##Inf => ##NaN\n  If a is zero => zero with the same sign as a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tan-double-"
+    asin "Returns the arc sine of an angle, in the range -pi/2 to pi/2.\n  If a is ##NaN or |a|>1 => ##NaN\n  If a is zero => zero with the same sign as a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#asin-double-"
+    acos "Returns the arc cosine of a, in the range 0.0 to pi.\n  If a is ##NaN or |a|>1 => ##NaN\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#acos-double-"
+    atan "Returns the arc tangent of a, in the range of -pi/2 to pi/2.\n  If a is ##NaN => ##NaN\n  If a is zero => zero with the same sign as a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan-double-"
+    to-radians "Converts an angle in degrees to an approximate equivalent angle in radians.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toRadians-double-"
+    to-degrees "Converts an angle in radians to an approximate equivalent angle in degrees.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toDegrees-double-"
+    exp "Returns Euler's number e raised to the power of a.\n  If a is ##NaN => ##NaN\n  If a is ##Inf => ##Inf\n  If a is ##-Inf => +0.0\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#exp-double-"
+    log "Returns the natural logarithm (base e) of a.\n  If a is ##NaN or negative => ##NaN\n  If a is ##Inf => ##Inf\n  If a is zero => ##-Inf\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log-double-"
+    log10 "Returns the logarithm (base 10) of a.\n  If a is ##NaN or negative => ##NaN\n  If a is ##Inf => ##Inf\n  If a is zero => ##-Inf\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log10-double-"
+    sqrt "Returns the positive square root of a.\n  If a is ##NaN or negative => ##NaN\n  If a is ##Inf => ##Inf\n  If a is zero => a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sqrt-double-"
+    cbrt "Returns the cube root of a.\n  If a is ##NaN => ##NaN\n  If a is ##Inf or ##-Inf => a\n  If a is zero => zero with sign matching a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cbrt-double-"
+    IEEE-remainder "Returns the remainder per IEEE 754 such that\n    remainder = dividend - divisor * n\n  where n is the integer closest to the exact value of dividend / divisor.\n  If two integers are equally close, then n is the even one.\n  If the remainder is zero, sign will match dividend.\n  If dividend or divisor is ##NaN, or dividend is ##Inf or ##-Inf, or divisor is zero => ##NaN\n  If dividend is finite and divisor is infinite => dividend\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#IEEEremainder-double-double-"
+    ceil "Returns the smallest double greater than or equal to a, and equal to a\n  mathematical integer.\n  If a is ##NaN or ##Inf or ##-Inf or already equal to an integer => a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ceil-double-"
+    floor "Returns the largest double less than or equal to a, and equal to a\n  mathematical integer.\n  If a is ##NaN or ##Inf or ##-Inf or already equal to an integer => a\n  If a is less than zero but greater than -1.0 => -0.0\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floor-double-"
+    rint "Returns the double closest to a and equal to a mathematical integer.\n  If two values are equally close, return the even one.\n  If a is ##NaN or ##Inf or ##-Inf or zero => a\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#rint-double-"
+    atan2 "Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta).\n  Computes the phase theta by computing an arc tangent of y/x in the range of -pi to pi.\n  For more details on special cases, see:\n  https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan2-double-double-"
+    pow "Returns the value of a raised to the power of b.\n  For more details on special cases, see:\n  https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#pow-double-double-"
+    round "Returns the closest long to a. If equally close to two values, return the one\n  closer to ##Inf.\n  If a is ##NaN => 0\n  If a is ##-Inf or < Long/MIN_VALUE => Long/MIN_VALUE\n  If a is ##Inf or > Long/MAX_VALUE => Long/MAX_VALUE\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#round-double-"
+    random "Returns a positive double between 0.0 and 1.0, chosen pseudorandomly with\n  approximately random distribution.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#random--"
+    add-exact "Returns the sum of x and y, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#addExact-long-long-"
+    subtract-exact "Returns the difference of x and y, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#subtractExact-long-long-"
+    multiply-exact "Returns the product of x and y, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#multiplyExact-long-long-"
+    increment-exact "Returns a incremented by 1, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#incrementExact-long-"
+    decrement-exact "Returns a decremented by 1, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#decrementExact-long-"
+    negate-exact "Returns the negation of a, throws ArithmeticException on overflow.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#negateExact-long-"
+    floor-div "Integer division that rounds to negative infinity (as opposed to zero).\n  The special case (floorDiv Long/MIN_VALUE -1) overflows and returns Long/MIN_VALUE.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorDiv-long-long-"
+    floor-mod "Integer modulus x - (floorDiv(x, y) * y). Sign matches y and is in the\n  range -|y| < r < |y|.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorMod-long-long-"
+    ulp "Returns the size of an ulp (unit in last place) for d.\n  If d is ##NaN => ##NaN\n  If d is ##Inf or ##-Inf => ##Inf\n  If d is zero => Double/MIN_VALUE\n  If d is +/- Double/MAX_VALUE => 2^971\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ulp-double-"
+    signum "Returns the signum function of d - zero for zero, 1.0 if >0, -1.0 if <0.\n  If d is ##NaN => ##NaN\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#signum-double-"
+    sinh "Returns the hyperbolic sine of x, (e^x - e^-x)/2.\n  If x is ##NaN => ##NaN\n  If x is ##Inf or ##-Inf or zero => x\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sinh-double-"
+    cosh "Returns the hyperbolic cosine of x, (e^x + e^-x)/2.\n  If x is ##NaN => ##NaN\n  If x is ##Inf or ##-Inf => ##Inf\n  If x is zero => 1.0\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cosh-double-"
+    tanh "Returns the hyperbolic tangent of x, sinh(x)/cosh(x).\n  If x is ##NaN => ##NaN\n  If x is zero => zero, with same sign\n  If x is ##Inf => +1.0\n  If x is ##-Inf => -1.0\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tanh-double-"
+    hypot "Returns sqrt(x^2 + y^2) without intermediate underflow or overflow.\n  If x or y is ##Inf or ##-Inf => ##Inf\n  If x or y is ##NaN and neither is ##Inf or ##-Inf => ##NaN\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#hypot-double-double-"
+    expm1 "Returns e^x - 1. Near 0, expm1(x)+1 is more accurate to e^x than exp(x).\n  If x is ##NaN => ##NaN\n  If x is ##Inf => #Inf\n  If x is ##-Inf => -1.0\n  If x is zero => x\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#expm1-double-"
+    log1p "Returns ln(1+x). For small values of x, log1p(x) is more accurate than\n  log(1.0+x).\n  If x is ##NaN or < -1 => ##NaN\n  If x is ##Inf => ##Inf\n  If x is -1 => ##-Inf\n  If x is 0 => 0 with sign matching x\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log1p-double-"
+    copy-sign "Returns a double with the magnitude of the first argument and the sign of\n  the second.\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#copySign-double-double-"
+    get-exponent "Returns the exponent of d.\n  If d is ##NaN, ##Inf, ##-Inf => Double/MAX_EXPONENT + 1\n  If d is zero or subnormal => Double/MIN_EXPONENT - 1\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#getExponent-double-"
+    next-after "Returns the adjacent floating point number to start in the direction of\n  the second argument. If the arguments are equal, the second is returned.\n  If either arg is #NaN => #NaN\n  If both arguments are signed zeros => direction\n  If start is +-Double/MIN_VALUE and direction would cause a smaller magnitude\n    => zero with sign matching start\n  If start is ##Inf or ##-Inf and direction would cause a smaller magnitude\n    => Double/MAX_VALUE with same sign as start\n  If start is equal to +=Double/MAX_VALUE and direction would cause a larger magnitude\n    => ##Inf or ##-Inf with sign matching start\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextAfter-double-double-"
+    next-up "Returns the adjacent double of d in the direction of ##Inf.\n  If d is ##NaN => ##NaN\n  If d is ##Inf => ##Inf\n  If d is zero => Double/MIN_VALUE\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextUp-double-"
+    next-down "Returns the adjacent double of d in the direction of ##-Inf.\n  If d is ##NaN => ##NaN\n  If d is ##-Inf => ##-Inf\n  If d is zero => -Double/MIN_VALUE\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-"
+    scalb "Returns d * 2^scaleFactor, scaling by a factor of 2. If the exponent\n  is between Double/MIN_EXPONENT and Double/MAX_EXPONENT, the answer is exact.\n  If d is ##NaN => ##NaN\n  If d is ##Inf or ##-Inf => ##Inf or ##-Inf respectively\n  If d is zero => zero of same sign as d\n  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-"
+    })
+
+(def FNS
+  '[sin cos tan asin acos atan toRadians toDegrees exp log log10
+    sqrt cbrt IEEEremainder ceil floor rint atan2 pow round random
+    addExact subtractExact multiplyExact incrementExact decrementExact negateExact
+    floorDiv floorMod ulp signum sinh cosh tanh hypot expm1 log1p copySign getExponent
+    nextAfter nextUp nextDown scalb])
+
+;; arg names to use (match java.lang.Math signatures)
+(def ARGS
+  '{
+    sin [a]
+    cos [a]
+    tan [a]
+    asin [a]
+    acos [a]
+    atan [a]
+    to-radians [deg]
+    to-degrees [r]
+    exp [a]
+    log [a]
+    log10 [a]
+    sqrt [a]
+    cbrt [a]
+    IEEE-remainder [dividend divisor]
+    ceil [a]
+    floor [a]
+    rint [a]
+    atan2 [y x]
+    pow [a b]
+    round [a]
+    random []
+    add-exact [x y]
+    subtract-exact [x y]
+    multiply-exact [x y]
+    increment-exact [a]
+    decrement-exact [a]
+    negate-exact [a]
+    floor-div [x y]
+    floor-mod [x y]
+    ulp [d]
+    signum [d]
+    sinh [x]
+    cosh [x]
+    tanh [x]
+    hypot [x y]
+    expm1 [x]
+    log1p [x]
+    copy-sign [magnitude sign]
+    get-exponent [d]
+    next-after [start direction]
+    next-up [d]
+    next-down [d]
+    scalb [d scaleFactor]
+    })
+
+;; type signature to use (otherwise automatically determined)
+(def ARGTYPES
+  '{scalb {:parameter-types [double int] :return-type double}})
diff --git a/src/clj/clojure/java/math.clj b/src/clj/clojure/math.clj
similarity index 83%
rename from src/clj/clojure/java/math.clj
rename to src/clj/clojure/math.clj
index 2d54fb52d7..c5b67b1f1c 100644
--- a/src/clj/clojure/java/math.clj
+++ b/src/clj/clojure/math.clj
@@ -17,8 +17,9 @@
 
   For more complete information, see:
   https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html"}
-  clojure.java.math
-  (:refer-clojure :exclude [min max]))
+  clojure.math)
+
+(set! *warn-on-reflection* true)
 
 (def
   ^{:doc "Constant for e, the base for natural logarithms.
@@ -44,7 +45,7 @@
   If a is zero => zero with the same sign as a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sin-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/sin ~a))
+   :inline (fn [a] `(Math/sin (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/sin a))
@@ -54,7 +55,7 @@
   If a is ##NaN, ##-Inf, ##Inf => ##NaN
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cos-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/cos ~a))
+   :inline (fn [a] `(Math/cos (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/cos a))
@@ -65,7 +66,7 @@
   If a is zero => zero with the same sign as a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tan-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/tan ~a))
+   :inline (fn [a] `(Math/tan (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/tan a))
@@ -76,7 +77,7 @@
   If a is zero => zero with the same sign as a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#asin-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/asin ~a))
+   :inline (fn [a] `(Math/asin (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/asin a))
@@ -86,7 +87,7 @@
   If a is ##NaN or |a|>1 => ##NaN
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#acos-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/acos ~a))
+   :inline (fn [a] `(Math/acos (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/acos a))
@@ -97,7 +98,7 @@
   If a is zero => zero with the same sign as a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/atan ~a))
+   :inline (fn [a] `(Math/atan (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/atan a))
@@ -106,7 +107,7 @@
   {:doc "Converts an angle in degrees to an approximate equivalent angle in radians.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toRadians-double-"
    :inline-arities #{1}
-   :inline (fn [deg] `(Math/toRadians ~deg))
+   :inline (fn [deg] `(Math/toRadians (double ~deg)))
    :added "1.11"}
   ^double [^double deg]
   (Math/toRadians deg))
@@ -115,7 +116,7 @@
   {:doc "Converts an angle in radians to an approximate equivalent angle in degrees.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#toDegrees-double-"
    :inline-arities #{1}
-   :inline (fn [r] `(Math/toDegrees ~r))
+   :inline (fn [r] `(Math/toDegrees (double ~r)))
    :added "1.11"}
   ^double [^double r]
   (Math/toDegrees r))
@@ -127,7 +128,7 @@
   If a is ##-Inf => +0.0
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#exp-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/exp ~a))
+   :inline (fn [a] `(Math/exp (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/exp a))
@@ -139,7 +140,7 @@
   If a is zero => ##-Inf
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/log ~a))
+   :inline (fn [a] `(Math/log (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/log a))
@@ -151,7 +152,7 @@
   If a is zero => ##-Inf
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log10-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/log10 ~a))
+   :inline (fn [a] `(Math/log10 (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/log10 a))
@@ -163,7 +164,7 @@
   If a is zero => a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sqrt-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/sqrt ~a))
+   :inline (fn [a] `(Math/sqrt (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/sqrt a))
@@ -175,7 +176,7 @@
   If a is zero => zero with sign matching a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cbrt-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/cbrt ~a))
+   :inline (fn [a] `(Math/cbrt (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/cbrt a))
@@ -190,7 +191,7 @@
   If dividend is finite and divisor is infinite => dividend
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#IEEEremainder-double-double-"
    :inline-arities #{2}
-   :inline (fn [dividend divisor] `(Math/IEEEremainder ~dividend ~divisor))
+   :inline (fn [dividend divisor] `(Math/IEEEremainder (double ~dividend) (double ~divisor)))
    :added "1.11"}
   ^double [^double dividend ^double divisor]
   (Math/IEEEremainder dividend divisor))
@@ -201,7 +202,7 @@
   If a is ##NaN or ##Inf or ##-Inf or already equal to an integer => a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ceil-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/ceil ~a))
+   :inline (fn [a] `(Math/ceil (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/ceil a))
@@ -213,7 +214,7 @@
   If a is less than zero but greater than -1.0 => -0.0
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floor-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/floor ~a))
+   :inline (fn [a] `(Math/floor (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/floor a))
@@ -224,7 +225,7 @@
   If a is ##NaN or ##Inf or ##-Inf or zero => a
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#rint-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/rint ~a))
+   :inline (fn [a] `(Math/rint (double ~a)))
    :added "1.11"}
   ^double [^double a]
   (Math/rint a))
@@ -235,7 +236,7 @@
   For more details on special cases, see:
   https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#atan2-double-double-"
    :inline-arities #{2}
-   :inline (fn [y x] `(Math/atan2 ~y ~x))
+   :inline (fn [y x] `(Math/atan2 (double ~y) (double ~x)))
    :added "1.11"}
   ^double [^double y ^double x]
   (Math/atan2 y x))
@@ -245,7 +246,7 @@
   For more details on special cases, see:
   https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#pow-double-double-"
    :inline-arities #{2}
-   :inline (fn [a b] `(Math/pow ~a ~b))
+   :inline (fn [a b] `(Math/pow (double ~a) (double ~b)))
    :added "1.11"}
   ^double [^double a ^double b]
   (Math/pow a b))
@@ -258,7 +259,7 @@
   If a is ##Inf or > Long/MAX_VALUE => Long/MAX_VALUE
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#round-double-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/round ~a))
+   :inline (fn [a] `(Math/round (double ~a)))
    :added "1.11"}
   ^long [^double a]
   (Math/round a))
@@ -277,7 +278,7 @@
   {:doc "Returns the sum of x and y, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#addExact-long-long-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/addExact ~x ~y))
+   :inline (fn [x y] `(Math/addExact (long ~x) (long ~y)))
    :added "1.11"}
   ^long [^long x ^long y]
   (Math/addExact x y))
@@ -286,7 +287,7 @@
   {:doc "Returns the difference of x and y, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#subtractExact-long-long-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/subtractExact ~x ~y))
+   :inline (fn [x y] `(Math/subtractExact (long ~x) (long ~y)))
    :added "1.11"}
   ^long [^long x ^long y]
   (Math/subtractExact x y))
@@ -295,7 +296,7 @@
   {:doc "Returns the product of x and y, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#multiplyExact-long-long-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/multiplyExact ~x ~y))
+   :inline (fn [x y] `(Math/multiplyExact (long ~x) (long ~y)))
    :added "1.11"}
   ^long [^long x ^long y]
   (Math/multiplyExact x y))
@@ -304,7 +305,7 @@
   {:doc "Returns a incremented by 1, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#incrementExact-long-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/incrementExact ~a))
+   :inline (fn [a] `(Math/incrementExact (long ~a)))
    :added "1.11"}
   ^long [^long a]
   (Math/incrementExact a))
@@ -313,16 +314,16 @@
   {:doc "Returns a decremented by 1, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#decrementExact-long-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/decrementExact ~a))
+   :inline (fn [a] `(Math/decrementExact (long ~a)))
    :added "1.11"}
   ^long [^long a]
   (Math/decrementExact a))
 
-(defn negative-exact
+(defn negate-exact
   {:doc "Returns the negation of a, throws ArithmeticException on overflow.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#negateExact-long-"
    :inline-arities #{1}
-   :inline (fn [a] `(Math/negateExact ~a))
+   :inline (fn [a] `(Math/negateExact (long ~a)))
    :added "1.11"}
   ^long [^long a]
   (Math/negateExact a))
@@ -332,7 +333,7 @@
   The special case (floorDiv Long/MIN_VALUE -1) overflows and returns Long/MIN_VALUE.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorDiv-long-long-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/floorDiv ~x ~y))
+   :inline (fn [x y] `(Math/floorDiv (long ~x) (long ~y)))
    :added "1.11"}
   ^long [^long x ^long y]
   (Math/floorDiv x y))
@@ -342,47 +343,11 @@
   range -|y| < r < |y|.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#floorMod-long-long-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/floorMod ~x ~y))
+   :inline (fn [x y] `(Math/floorMod (long ~x) (long ~y)))
    :added "1.11"}
   ^long [^long x ^long y]
   (Math/floorMod x y))
 
-(defn abs
-  {:doc "Returns the absolute value of a (long or double).
-  If not negative, a is returned, else negation of a is returned.
-  If a is Long/MIN_VALUE => Long/MIN_VALUE
-  If a is a double and zero => +0.0
-  If a is a double and ##Inf or ##-Inf => ##Inf
-  If a is a double and ##NaN => ##NaN
-  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#abs-long-"
-   :inline-arities #{1}
-   :inline (fn [a] `(Math/abs ~a))
-   :added "1.11"}
-  [a]
-  (Math/abs a))
-
-(defn max
-  {:doc "Returns the greater of a or b.
-  If doubles and a or b is ##NaN => ##NaN
-  If doubles and one is negative zero, other positive zero => positive zero
-  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#max-long-long-"
-   :inline-arities #{2}
-   :inline (fn [a b] `(Math/max ~a ~b))
-   :added "1.11"}
-  [a b]
-  (Math/max a b))
-
-(defn min
-  {:doc "Returns the lesser of a or b.
-  If doubles and a or b is ##NaN => ##NaN
-  If doubles and one is negative zero, other positive zero => negative zero
-  See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#min-double-double-"
-   :inline-arities #{2}
-   :inline (fn [p0 p1] `(Math/min ~p0 ~p1))
-   :added "1.11"}
-  [p0 p1]
-  (Math/min p0 p1))
-
 (defn ulp
   {:doc "Returns the size of an ulp (unit in last place) for d.
   If d is ##NaN => ##NaN
@@ -391,7 +356,7 @@
   If d is +/- Double/MAX_VALUE => 2^971
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#ulp-double-"
    :inline-arities #{1}
-   :inline (fn [d] `(Math/ulp ~d))
+   :inline (fn [d] `(Math/ulp (double ~d)))
    :added "1.11"}
   ^double [^double d]
   (Math/ulp d))
@@ -399,10 +364,9 @@
 (defn signum
   {:doc "Returns the signum function of d - zero for zero, 1.0 if >0, -1.0 if <0.
   If d is ##NaN => ##NaN
-  If d is ##Inf or ##-Inf => d
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#signum-double-"
    :inline-arities #{1}
-   :inline (fn [d] `(Math/signum ~d))
+   :inline (fn [d] `(Math/signum (double ~d)))
    :added "1.11"}
   ^double [^double d]
   (Math/signum d))
@@ -413,7 +377,7 @@
   If x is ##Inf or ##-Inf or zero => x
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#sinh-double-"
    :inline-arities #{1}
-   :inline (fn [x] `(Math/sinh ~x))
+   :inline (fn [x] `(Math/sinh (double ~x)))
    :added "1.11"}
   ^double [^double x]
   (Math/sinh x))
@@ -425,7 +389,7 @@
   If x is zero => 1.0
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#cosh-double-"
    :inline-arities #{1}
-   :inline (fn [x] `(Math/cosh ~x))
+   :inline (fn [x] `(Math/cosh (double ~x)))
    :added "1.11"}
   ^double [^double x]
   (Math/cosh x))
@@ -438,7 +402,7 @@
   If x is ##-Inf => -1.0
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#tanh-double-"
    :inline-arities #{1}
-   :inline (fn [x] `(Math/tanh ~x))
+   :inline (fn [x] `(Math/tanh (double ~x)))
    :added "1.11"}
   ^double [^double x]
   (Math/tanh x))
@@ -449,7 +413,7 @@
   If x or y is ##NaN and neither is ##Inf or ##-Inf => ##NaN
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#hypot-double-double-"
    :inline-arities #{2}
-   :inline (fn [x y] `(Math/hypot ~x ~y))
+   :inline (fn [x y] `(Math/hypot (double ~x) (double ~y)))
    :added "1.11"}
   ^double [^double x ^double y]
   (Math/hypot x y))
@@ -462,7 +426,7 @@
   If x is zero => x
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#expm1-double-"
    :inline-arities #{1}
-   :inline (fn [x] `(Math/expm1 ~x))
+   :inline (fn [x] `(Math/expm1 (double ~x)))
    :added "1.11"}
   ^double [^double x]
   (Math/expm1 x))
@@ -471,10 +435,12 @@
   {:doc "Returns ln(1+x). For small values of x, log1p(x) is more accurate than
   log(1.0+x).
   If x is ##NaN or < -1 => ##NaN
-  If x is ##Inf or ##-Inf or x => x
+  If x is ##Inf => ##Inf
+  If x is -1 => ##-Inf
+  If x is 0 => 0 with sign matching x
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#log1p-double-"
    :inline-arities #{1}
-   :inline (fn [x] `(Math/log1p ~x))
+   :inline (fn [x] `(Math/log1p (double ~x)))
    :added "1.11"}
   ^double [^double x]
   (Math/log1p x))
@@ -484,7 +450,7 @@
   the second.
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#copySign-double-double-"
    :inline-arities #{2}
-   :inline (fn [magnitude sign] `(Math/copySign ~magnitude ~sign))
+   :inline (fn [magnitude sign] `(Math/copySign (double ~magnitude) (double ~sign)))
    :added "1.11"}
   ^double [^double magnitude ^double sign]
   (Math/copySign magnitude sign))
@@ -495,7 +461,7 @@
   If d is zero or subnormal => Double/MIN_EXPONENT - 1
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#getExponent-double-"
    :inline-arities #{1}
-   :inline (fn [d] `(Math/getExponent ~d))
+   :inline (fn [d] `(Math/getExponent (double ~d)))
    :added "1.11"}
   [^double d]
   (Math/getExponent d))
@@ -513,7 +479,7 @@
     => ##Inf or ##-Inf with sign matching start
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextAfter-double-double-"
    :inline-arities #{2}
-   :inline (fn [start direction] `(Math/nextAfter ~start ~direction))
+   :inline (fn [start direction] `(Math/nextAfter (double ~start) (double ~direction)))
    :added "1.11"}
   ^double [^double start ^double direction]
   (Math/nextAfter start direction))
@@ -525,7 +491,7 @@
   If d is zero => Double/MIN_VALUE
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextUp-double-"
    :inline-arities #{1}
-   :inline (fn [d] `(Math/nextUp ~d))
+   :inline (fn [d] `(Math/nextUp (double ~d)))
    :added "1.11"}
   ^double [^double d]
   (Math/nextUp d))
@@ -533,11 +499,11 @@
 (defn next-down
   {:doc "Returns the adjacent double of d in the direction of ##-Inf.
   If d is ##NaN => ##NaN
-  If d is ##Inf => ##-Inf
-  If d is zero => Double/MIN_VALUE
+  If d is ##-Inf => ##-Inf
+  If d is zero => -Double/MIN_VALUE
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-"
    :inline-arities #{1}
-   :inline (fn [d] `(Math/nextDown ~d))
+   :inline (fn [d] `(Math/nextDown (double ~d)))
    :added "1.11"}
   ^double [^double d]
   (Math/nextDown d))
@@ -549,8 +515,9 @@
   If d is ##Inf or ##-Inf => ##Inf or ##-Inf respectively
   If d is zero => zero of same sign as d
   See: https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#nextDown-double-"
-   :inline-arities #{1}
-   :inline (fn [d scaleFactor] `(Math/scalb ~d ~scaleFactor))
+   :inline-arities #{2}
+   :inline (fn [d scaleFactor] `(Math/scalb (double ~d) (int ~scaleFactor)))
    :added "1.11"}
   ^double [^double d scaleFactor]
-  (Math/scalb d scaleFactor))
\ No newline at end of file
+  (Math/scalb d (int scaleFactor)))
+
diff --git a/test/clojure/test_clojure/math.clj b/test/clojure/test_clojure/math.clj
new file mode 100644
index 0000000000..63975e7505
--- /dev/null
+++ b/test/clojure/test_clojure/math.clj
@@ -0,0 +1,320 @@
+;   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+(ns clojure.test-clojure.math
+  (:require
+    [clojure.test :refer :all]
+    [clojure.math :as m]))
+
+(set! *warn-on-reflection* true)
+
+(defn neg-zero?
+  [^double d]
+  (and (zero? d) (< (Double/compare d 0.0) 0)))
+
+(defn pos-zero?
+  [^double d]
+  (and (zero? d) (not (< (Double/compare d 0.0) 0))))
+
+(deftest test-sin
+  (is (NaN? (m/sin ##NaN)))
+  (is (NaN? (m/sin ##-Inf)))
+  (is (NaN? (m/sin ##Inf)))
+  (is (pos-zero? (m/sin 0.0)))
+  (is (neg-zero? (m/sin -0.0)))
+  (is (= (m/sin m/PI) (- (m/sin (- m/PI))))))
+
+(deftest test-cos
+  (is (NaN? (m/cos ##NaN)))
+  (is (NaN? (m/cos ##-Inf)))
+  (is (NaN? (m/cos ##Inf)))
+  (is (= 1.0 (m/cos 0.0) (m/cos -0.0)))
+  (is (= (m/cos m/PI) (m/cos (- m/PI)))))
+
+(deftest test-tan
+  (is (NaN? (m/tan ##NaN)))
+  (is (NaN? (m/tan ##-Inf)))
+  (is (NaN? (m/tan ##Inf)))
+  (is (pos-zero? (m/tan 0.0)))
+  (is (neg-zero? (m/tan -0.0)))
+  (is (= (- (m/tan m/PI)) (m/tan (- m/PI)))))
+
+(deftest test-asin
+  (is (NaN? (m/asin ##NaN)))
+  (is (NaN? (m/asin 2.0)))
+  (is (NaN? (m/asin -2.0)))
+  (is (zero? (m/asin -0.0))))
+
+(deftest test-acos
+  (is (NaN? (m/acos ##NaN)))
+  (is (NaN? (m/acos -2.0)))
+  (is (NaN? (m/acos 2.0)))
+  (is (= m/PI (* 2 (m/acos 0.0)))))
+
+(deftest test-atan
+  (is (NaN? (m/atan ##NaN)))
+  (is (pos-zero? (m/atan 0.0)))
+  (is (neg-zero? (m/atan -0.0)))
+  (is (= 0.7853981633974483 (m/atan 1))))
+
+(deftest test-radians-degrees-roundtrip
+  (doseq [d (range 0.0 360.0 5.0)]
+    (is (= (m/round d) (m/round (-> d m/to-radians m/to-degrees))))))
+
+(deftest test-exp
+  (is (NaN? (m/exp ##NaN)))
+  (is (= ##Inf (m/exp ##Inf)))
+  (is (pos-zero? (m/exp ##-Inf)))
+  (is (= 1.0 (m/exp 0.0)))
+  (is (= m/E (m/exp 1))))
+
+(deftest test-log
+  (is (NaN? (m/log ##NaN)))
+  (is (NaN? (m/log -1.0)))
+  (is (= ##Inf (m/log ##Inf)))
+  (is (= ##-Inf (m/log 0.0)))
+  (is (= 1.0 (m/log m/E))))
+
+(deftest test-log10
+  (is (NaN? (m/log10 ##NaN)))
+  (is (NaN? (m/log10 -1.0)))
+  (is (= ##Inf (m/log10 ##Inf)))
+  (is (= ##-Inf (m/log10 0.0)))
+  (is (= 1.0 (m/log10 10))))
+
+(deftest test-sqrt
+  (is (NaN? (m/sqrt ##NaN)))
+  (is (NaN? (m/sqrt -1.0)))
+  (is (= ##Inf (m/sqrt ##Inf)))
+  (is (pos-zero? (m/sqrt 0)))
+  (is (= 2.0 (m/sqrt 4.0))))
+
+(deftest test-cbrt
+  (is (NaN? (m/cbrt ##NaN)))
+  (is (= ##-Inf (m/cbrt ##-Inf)))
+  (is (= ##Inf (m/cbrt ##Inf)))
+  (is (pos-zero? (m/cbrt 0)))
+  (is (= 2.0 (m/cbrt 8.0))))
+
+(deftest test-IEEE-remainder
+  (is (NaN? (m/IEEE-remainder ##NaN 1.0)))
+  (is (NaN? (m/IEEE-remainder 1.0 ##NaN)))
+  (is (NaN? (m/IEEE-remainder ##Inf 2.0)))
+  (is (NaN? (m/IEEE-remainder ##-Inf 2.0)))
+  (is (NaN? (m/IEEE-remainder 2 0.0)))
+  (is (= 1.0 (m/IEEE-remainder 5.0 4.0))))
+
+(deftest test-ceil
+  (is (NaN? (m/ceil ##NaN)))
+  (is (= ##Inf (m/ceil ##Inf)))
+  (is (= ##-Inf (m/ceil ##-Inf)))
+  (is (= 4.0 (m/ceil m/PI))))
+
+(deftest test-floor
+  (is (NaN? (m/floor ##NaN)))
+  (is (= ##Inf (m/floor ##Inf)))
+  (is (= ##-Inf (m/floor ##-Inf)))
+  (is (= 3.0 (m/floor m/PI))))
+
+(deftest test-rint
+  (is (NaN? (m/rint ##NaN)))
+  (is (= ##Inf (m/rint ##Inf)))
+  (is (= ##-Inf (m/rint ##-Inf)))
+  (is (= 1.0 (m/rint 1.2)))
+  (is (neg-zero? (m/rint -0.01))))
+
+(deftest test-atan2
+  (is (NaN? (m/atan2 ##NaN 1.0)))
+  (is (NaN? (m/atan2 1.0 ##NaN)))
+  (is (pos-zero? (m/atan2 0.0 1.0)))
+  (is (neg-zero? (m/atan2 -0.0 1.0)))
+  (is (= m/PI (m/atan2 0.0 -1.0)))
+  (is (= (- m/PI) (m/atan2 -0.0 -1.0)))
+  (is (= m/PI (* 2.0 (m/atan2 1.0 0.0))))
+  (is (= m/PI (* -2.0 (m/atan2 -1.0 0.0))))
+  (is (= m/PI (* 4.0 (m/atan2 ##Inf ##Inf))))
+  (is (= m/PI (/ (* 4.0 (m/atan2 ##Inf ##-Inf)) 3.0)))
+  (is (= m/PI (* -4.0 (m/atan2 ##-Inf ##Inf))))
+  (is (= m/PI (/ (* -4.0 (m/atan2 ##-Inf ##-Inf)) 3.0))))
+
+(deftest test-pow
+  (is (= 1.0 (m/pow 4.0 0.0)))
+  (is (= 1.0 (m/pow 4.0 -0.0)))
+  (is (= 4.2 (m/pow 4.2 1.0)))
+  (is (NaN? (m/pow 4.2 ##NaN)))
+  (is (NaN? (m/pow ##NaN 2.0)))
+  (is (= ##Inf (m/pow 2.0 ##Inf)))
+  (is (= ##Inf (m/pow 0.5 ##-Inf)))
+  (is (= 0.0 (m/pow 2.0 ##-Inf)))
+  (is (= 0.0 (m/pow 0.5 ##Inf)))
+  (is (NaN? (m/pow 1.0 ##Inf)))
+  (is (pos-zero? (m/pow 0.0 1.5)))
+  (is (pos-zero? (m/pow ##Inf -2.0)))
+  (is (= ##Inf (m/pow 0.0 -2.0)))
+  (is (= ##Inf (m/pow ##Inf 2.0)))
+  (is (pos-zero? (m/pow -0.0 1.5)))
+  (is (pos-zero? (m/pow ##-Inf -1.5)))
+  (is (neg-zero? (m/pow -0.0 3.0)))
+  (is (neg-zero? (m/pow ##-Inf -3.0)))
+  (is (= ##Inf (m/pow -0.0 -1.5)))
+  (is (= ##Inf (m/pow ##-Inf 2.5)))
+  (is (= ##-Inf (m/pow -0.0 -3.0)))
+  (is (= ##-Inf (m/pow ##-Inf 3.0)))
+  (is (= 4.0 (m/pow -2.0 2.0)))
+  (is (= -8.0 (m/pow -2.0 3.0)))
+  (is (= 8.0 (m/pow 2.0 3.0))))
+
+(deftest test-round
+  (is (= 0 (m/round ##NaN)))
+  (is (= Long/MIN_VALUE (m/round ##-Inf)))
+  (is (= Long/MIN_VALUE (m/round (- Long/MIN_VALUE 2.0))))
+  (is (= Long/MAX_VALUE (m/round ##Inf)))
+  (is (= Long/MAX_VALUE (m/round (+ Long/MAX_VALUE 2.0))))
+  (is (= 4 (m/round 3.5))))
+
+(deftest test-add-exact
+  (try
+    (m/add-exact Long/MAX_VALUE 1)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-subtract-exact
+  (try
+    (m/subtract-exact Long/MIN_VALUE 1)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-multiply-exact
+  (try
+    (m/multiply-exact Long/MAX_VALUE 2)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-increment-exact
+  (try
+    (m/increment-exact Long/MAX_VALUE)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-decrement-exact
+  (try
+    (m/decrement-exact Long/MIN_VALUE)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-negate-exact
+  (is (= (inc Long/MIN_VALUE) (m/negate-exact Long/MAX_VALUE)))
+  (try
+    (m/negate-exact Long/MIN_VALUE)
+    (is false)
+    (catch ArithmeticException _
+      (is true))))
+
+(deftest test-floor-div
+  (is (= Long/MIN_VALUE (m/floor-div Long/MIN_VALUE -1)))
+  (is (= -1 (m/floor-div -2 5))))
+
+(deftest test-floor-mod
+  (is (= 3 (m/floor-mod -2 5))))
+
+(deftest test-ulp
+  (is (NaN? (m/ulp ##NaN)))
+  (is (= ##Inf (m/ulp ##Inf)))
+  (is (= ##Inf (m/ulp ##-Inf)))
+  (is (= Double/MIN_VALUE (m/ulp 0.0)))
+  (is (= (m/pow 2 971) (m/ulp Double/MAX_VALUE)))
+  (is (= (m/pow 2 971) (m/ulp (- Double/MAX_VALUE)))))
+
+(deftest test-signum
+  (is (NaN? (m/signum ##NaN)))
+  (is (zero? (m/signum 0.0)))
+  (is (zero? (m/signum -0.0)))
+  (is (= 1.0 (m/signum 42.0)))
+  (is (= -1.0 (m/signum -42.0))))
+
+(deftest test-sinh
+  (is (NaN? (m/sinh ##NaN)))
+  (is (= ##Inf (m/sinh ##Inf)))
+  (is (= ##-Inf (m/sinh ##-Inf)))
+  (is (= 0.0 (m/sinh 0.0))))
+
+(deftest test-cosh
+  (is (NaN? (m/cosh ##NaN)))
+  (is (= ##Inf (m/cosh ##Inf)))
+  (is (= ##Inf (m/cosh ##-Inf)))
+  (is (= 1.0 (m/cosh 0.0))))
+
+(deftest test-tanh
+  (is (NaN? (m/tanh ##NaN)))
+  (is (= 1.0 (m/tanh ##Inf)))
+  (is (= -1.0 (m/tanh ##-Inf)))
+  (is (= 0.0 (m/tanh 0.0))))
+
+(deftest test-hypot
+  (is (= ##Inf (m/hypot 1.0 ##Inf)))
+  (is (= ##Inf (m/hypot ##Inf 1.0)))
+  (is (NaN? (m/hypot ##NaN 1.0)))
+  (is (NaN? (m/hypot 1.0 ##NaN)))
+  (is (= 13.0 (m/hypot 5.0 12.0))))
+
+(deftest test-expm1
+  (is (NaN? (m/expm1 ##NaN)))
+  (is (= ##Inf (m/expm1 ##Inf)))
+  (is (= -1.0 (m/expm1 ##-Inf)))
+  (is (= 0.0 (m/expm1 0.0))))
+
+(deftest test-log1p
+  (is (NaN? (m/log1p ##NaN)))
+  (is (= ##Inf (m/log1p ##Inf)))
+  (is (= ##-Inf (m/log1p -1.0)))
+  (is (pos-zero? (m/log1p 0.0)))
+  (is (neg-zero? (m/log1p -0.0))))
+
+(deftest test-copy-sign
+  (is (= 1.0 (m/copy-sign 1.0 42.0)))
+  (is (= -1.0 (m/copy-sign 1.0 -42.0)))
+  (is (= -1.0 (m/copy-sign 1.0 ##-Inf))))
+
+(deftest test-get-exponent
+  (is (= (inc Double/MAX_EXPONENT) (m/get-exponent ##NaN)))
+  (is (= (inc Double/MAX_EXPONENT) (m/get-exponent ##Inf)))
+  (is (= (inc Double/MAX_EXPONENT) (m/get-exponent ##-Inf)))
+  (is (= (dec Double/MIN_EXPONENT) (m/get-exponent 0.0)))
+  (is (= 0 (m/get-exponent 1.0)))
+  (is (= 13 (m/get-exponent 12345.678))))
+
+(deftest test-next-after
+  (is (NaN? (m/next-after ##NaN 1)))
+  (is (NaN? (m/next-after 1 ##NaN)))
+  (is (pos-zero? (m/next-after 0.0 0.0)))
+  (is (neg-zero? (m/next-after -0.0 -0.0)))
+  (is (= Double/MAX_VALUE (m/next-after ##Inf 1.0)))
+  (is (pos-zero? (m/next-after Double/MIN_VALUE -1.0))))
+
+(deftest test-next-up
+  (is (NaN? (m/next-up ##NaN)))
+  (is (= ##Inf (m/next-up ##Inf)))
+  (is (= Double/MIN_VALUE (m/next-up 0.0))))
+
+(deftest test-next-down
+  (is (NaN? (m/next-down ##NaN)))
+  (is (= ##-Inf (m/next-down ##-Inf)))
+  (is (= (- Double/MIN_VALUE) (m/next-down 0.0))))
+
+(deftest test-scalb
+  (is (NaN? (m/scalb ##NaN 1)))
+  (is (= ##Inf (m/scalb ##Inf 1)))
+  (is (= ##-Inf (m/scalb ##-Inf 1)))
+  (is (pos-zero? (m/scalb 0.0 2)))
+  (is (neg-zero? (m/scalb -0.0 2)))
+  (is (= 32.0 (m/scalb 2.0 4))))

From ff61321179a0b0f7d2c17a394ade80465ac15c28 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Mon, 10 Jan 2022 13:52:31 -0600
Subject: [PATCH 42/78] CLJ-2673 Implement abs/min/max in clojure.core with
 polymorphic numeric support

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj              | 12 +++++++
 src/jvm/clojure/lang/Numbers.java     | 51 +++++++++++++++++++++------
 test/clojure/test_clojure/numbers.clj | 14 ++++++++
 3 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 0dba6fcd97..7c8cb1804a 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1134,6 +1134,18 @@
   ([x y & more]
    (reduce1 min (min x y) more)))
 
+(defn abs
+  {:doc "Returns the absolute value of a.
+  If a is Long/MIN_VALUE => Long/MIN_VALUE
+  If a is a double and zero => +0.0
+  If a is a double and ##Inf or ##-Inf => ##Inf
+  If a is a double and ##NaN => ##NaN"
+   :inline-arities #{1}
+   :inline (fn [a] `(clojure.lang.Numbers/abs ~a))
+   :added "1.11"}
+  [a]
+  (clojure.lang.Numbers/abs a))
+
 (defn dec'
   "Returns a number one less than num. Supports arbitrary precision.
   See also: dec"
diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java
index fa13cba62c..6405bc2193 100644
--- a/src/jvm/clojure/lang/Numbers.java
+++ b/src/jvm/clojure/lang/Numbers.java
@@ -68,6 +68,8 @@ static interface Ops{
 	public Number dec(Number x);
 	public Number decP(Number x);
 	public Number unchecked_dec(Number x);
+
+	public Number abs(Number x);
 }
 
 static abstract class OpsP implements Ops{
@@ -619,6 +621,10 @@ public Number unchecked_dec(Number x){
 		long val = x.longValue();
 		return num(Numbers.unchecked_dec(val));
 	}
+
+	public Number abs(Number x){
+		return num(Math.abs(x.longValue()));
+	}
 }
 
 final static class DoubleOps extends OpsP{
@@ -706,6 +712,10 @@ public Number inc(Number x){
 	public Number dec(Number x){
 		return Double.valueOf(x.doubleValue() - 1);
 	}
+
+	public Number abs(Number x) {
+		return num(Math.abs(x.doubleValue()));
+	}
 }
 
 final static class RatioOps extends OpsP{
@@ -837,6 +847,11 @@ public Number dec(Number x){
 		return Numbers.add(x, -1);
 	}
 
+	public Number abs(Number x) {
+		Ratio r = (Ratio) x;
+		return new Ratio(r.numerator.abs(), r.denominator);
+	}
+
 }
 
 final static class BigIntOps extends OpsP{
@@ -935,6 +950,10 @@ public Number dec(Number x){
 		BigInteger bx = toBigInteger(x);
 		return BigInt.fromBigInteger(bx.subtract(BigInteger.ONE));
 	}
+
+	public Number abs(Number x) {
+		return BigInt.fromBigInteger(toBigInteger(x).abs());
+	}
 }
 
 
@@ -1054,6 +1073,14 @@ public Number dec(Number x){
 		       ? bx.subtract(BigDecimal.ONE)
 		       : bx.subtract(BigDecimal.ONE, mc);
 	}
+
+	public Number abs(Number x) {
+		MathContext mc = (MathContext) MATH_CONTEXT.deref();
+		BigDecimal bx = (BigDecimal) x;
+		return mc == null
+				? ((BigDecimal) x).abs()
+				: ((BigDecimal) x).abs(mc);
+	}
 }
 
 static final LongOps LONG_OPS = new LongOps();
@@ -4068,11 +4095,7 @@ static public Object max(long x, double y){
 
 
 static public long max(long x, long y){
-	if(x > y) {
-		return x;
-	} else {
-		return y;
-	}
+	return Math.max(x, y);
 }
 
 
@@ -4166,11 +4189,7 @@ static public Object min(long x, double y){
 
 
 static public long min(long x, long y){
-	if(x < y) {
-		return x;
-	} else {
-		return y;
-	}
+	return Math.min(x, y);
 }
 
 static public Object min(long x, Object y){
@@ -4221,4 +4240,16 @@ static public Object min(Object x, Object y){
 	}
 }
 
+static public long abs(long x){
+	return Math.abs(x);
+}
+
+static public double abs(double x){
+	return Math.abs(x);
+}
+
+static public Number abs(Object x) {
+	return ops(x).abs((Number)x);
+}
+
 }
diff --git a/test/clojure/test_clojure/numbers.clj b/test/clojure/test_clojure/numbers.clj
index 26140a7c29..cc62a63c89 100644
--- a/test/clojure/test_clojure/numbers.clj
+++ b/test/clojure/test_clojure/numbers.clj
@@ -644,6 +644,20 @@ Math/pow overflows to Infinity."
     (is (= java.lang.Long (class (min 1.0 2.0 -10))))
     (is (= java.lang.Double (class (min 1 2 -10.0 3 4 5))))))
 
+(deftest test-abs
+  (are [in ex] (= ex (abs in))
+    -1 1
+    1 1
+    Long/MIN_VALUE Long/MIN_VALUE ;; special case!
+    -1.0 1.0
+    -0.0 0.0
+    ##-Inf ##Inf
+    ##Inf ##Inf
+    -123.456M 123.456M
+    -123N 123N
+    -1/5 1/5)
+  (is (NaN? (abs ##NaN))))
+
 (deftest clj-868
   (testing "min/max: NaN is contagious"
     (letfn [(fnan? [^Float x] (Float/isNaN x))

From bf0c0e23a0e05509c785598be19b01c2b8e80bb5 Mon Sep 17 00:00:00 2001
From: Paula Gearon 
Date: Tue, 14 Dec 2021 10:44:30 -0500
Subject: [PATCH 43/78] CLJ-2679 quoting condition values that are generated
 for case-hash collisions

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj              | 2 +-
 test/clojure/test_clojure/control.clj | 9 ++++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 7c8cb1804a..72a4548eb3 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -6702,7 +6702,7 @@ fails, attempts to require sym's namespace and retries."
                       (next ks) (next vs))
                     m))
         assoc-multi (fn [m h bucket]
-                      (let [testexprs (apply concat bucket)
+                      (let [testexprs (mapcat (fn [kv] [(list 'quote (first kv)) (second kv)]) bucket)
                             expr `(condp = ~expr-sym ~@testexprs ~default)]
                         (assoc m h expr)))
         hmap (reduce1
diff --git a/test/clojure/test_clojure/control.clj b/test/clojure/test_clojure/control.clj
index 92846ad38d..f3fe436b45 100644
--- a/test/clojure/test_clojure/control.clj
+++ b/test/clojure/test_clojure/control.clj
@@ -421,7 +421,14 @@
          :b 1
          :c -2
          :d 4294967296
-         :d 3))
+         :d 3)
+    (are [result input] (= result (case input
+                                    #{a} :set
+                                    :foo :keyword
+                                    a :symbol))
+         :symbol 'a
+         :keyword :foo
+         :set '#{a}))
   (testing "test warn for hash collision"
     (should-print-err-message
      #"Performance warning, .*:\d+ - hash collision of some case test constants; if selected, those entries will be tested sequentially..*\r?\n"

From 0cbf655d181c2de8cd30bf234e40488fc94dbdfa Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 30 Nov 2021 08:19:41 -0600
Subject: [PATCH 44/78] CLJ-2670 - Use Math exact methods where possible for
 perf

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/Numbers.java     | 29 ++++++---------------------
 src/jvm/clojure/lang/RT.java          |  5 +----
 test/clojure/test_clojure/numbers.clj |  2 +-
 3 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java
index 6405bc2193..82d8e6914c 100644
--- a/src/jvm/clojure/lang/Numbers.java
+++ b/src/jvm/clojure/lang/Numbers.java
@@ -1915,10 +1915,7 @@ static public Number unchecked_dec(Object x){
 static public double remainder(long x, double y){return remainder((double)x,y);}
 
 static public long add(long x, long y){
-	long ret = x + y;
-	if ((ret ^ x) < 0 && (ret ^ y) < 0)
-		return throwIntOverflow();
-	return ret;
+	return Math.addExact(x, y);
 }
 
 static public Number addP(long x, long y){
@@ -1929,10 +1926,7 @@ static public Number addP(long x, long y){
 }
 
 static public long minus(long x, long y){
-	long ret = x - y;
-	if (((ret ^ x) < 0 && (ret ^ ~y) < 0))
-		return throwIntOverflow();
-	return ret;
+	return Math.subtractExact(x, y);
 }
 
 static public Number minusP(long x, long y){
@@ -1943,9 +1937,7 @@ static public Number minusP(long x, long y){
 }
 
 static public long minus(long x){
-	if(x == Long.MIN_VALUE)
-		return throwIntOverflow();
-	return -x;
+	return Math.negateExact(x);
 }
 
 static public Number minusP(long x){
@@ -1955,9 +1947,7 @@ static public Number minusP(long x){
 }
 
 static public long inc(long x){
-	if(x == Long.MAX_VALUE)
-		return throwIntOverflow();
-	return x + 1;
+	return Math.incrementExact(x);
 }
 
 static public Number incP(long x){
@@ -1967,9 +1957,7 @@ static public Number incP(long x){
 }
 
 static public long dec(long x){
-	if(x == Long.MIN_VALUE)
-		return throwIntOverflow();
-	return x - 1;
+	return Math.decrementExact(x);
 }
 
 static public Number decP(long x){
@@ -1980,12 +1968,7 @@ static public Number decP(long x){
 
 
 static public long multiply(long x, long y){
-  if (x == Long.MIN_VALUE && y < 0)
-		return throwIntOverflow();
-	long ret = x * y;
-	if (y != 0 && ret/y != x)
-		return throwIntOverflow();
-	return ret;
+	return Math.multiplyExact(x, y);
 }
 
 static public Number multiplyP(long x, long y){
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index 74399cf15f..5d20ef4964 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -1244,10 +1244,7 @@ static public int intCast(float x){
 }
 
 static public int intCast(long x){
-	int i = (int) x;
-	if(i != x)
-		throw new IllegalArgumentException("Value out of range for int: " + x);
-	return i;
+	return Math.toIntExact(x);
 }
 
 static public int intCast(double x){
diff --git a/test/clojure/test_clojure/numbers.clj b/test/clojure/test_clojure/numbers.clj
index cc62a63c89..a6b61605ea 100644
--- a/test/clojure/test_clojure/numbers.clj
+++ b/test/clojure/test_clojure/numbers.clj
@@ -181,7 +181,7 @@
       (let [wrapped (fn [x]
                       (try
                        (f x)
-                       (catch IllegalArgumentException e :error)))]
+                       (catch RuntimeException e :error)))]
         (is (= vals (map wrapped inputs)))))))
 
 ;; *** Functions ***

From 4b9eadccce2aaf97e64bcc8e35c05c529df8fdd2 Mon Sep 17 00:00:00 2001
From: Hugo Duncan 
Date: Wed, 12 Mar 2014 14:38:38 -0400
Subject: [PATCH 45/78] Fix quoting in assert-predicate

Signed-off-by: Alex Miller 
---
 src/clj/clojure/test.clj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/clj/clojure/test.clj b/src/clj/clojure/test.clj
index 0ab20a75a3..fc3536d7f3 100644
--- a/src/clj/clojure/test.clj
+++ b/src/clj/clojure/test.clj
@@ -447,7 +447,7 @@
            result# (apply ~pred values#)]
        (if result#
          (do-report {:type :pass, :message ~msg,
-                  :expected '~form, :actual (cons ~pred values#)})
+                  :expected '~form, :actual (cons '~pred values#)})
          (do-report {:type :fail, :message ~msg,
                   :expected '~form, :actual (list '~'not (cons '~pred values#))}))
        result#)))

From f08a81ba946cb7afaea859822bba1f52004326ec Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Mon, 20 Sep 2021 15:06:45 -0500
Subject: [PATCH 46/78] CLJ-2234 - Use explicit multimethod hierarchy in
 preference checks

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/MultiFn.java          | 26 +++++++--------
 test/clojure/test_clojure/multimethods.clj | 37 ++++++++++++++++++++++
 2 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/jvm/clojure/lang/MultiFn.java b/src/jvm/clojure/lang/MultiFn.java
index fd37e2a085..44ac1ce1c0 100644
--- a/src/jvm/clojure/lang/MultiFn.java
+++ b/src/jvm/clojure/lang/MultiFn.java
@@ -85,7 +85,7 @@ public MultiFn preferMethod(Object dispatchValX, Object dispatchValY) {
 	rw.writeLock().lock();
 	try
 		{
-		if(prefers(dispatchValY, dispatchValX))
+		if(prefers(hierarchy.deref(), dispatchValY, dispatchValX))
 			throw new IllegalStateException(
 					String.format("Preference conflict in multimethod '%s': %s is already preferred to %s",
 					              name, dispatchValY, dispatchValX));
@@ -102,29 +102,29 @@ public MultiFn preferMethod(Object dispatchValX, Object dispatchValY) {
 		}
 }
 
-private boolean prefers(Object x, Object y) {
+private boolean prefers(Object hierarchy, Object x, Object y) {
 	IPersistentSet xprefs = (IPersistentSet) getPreferTable().valAt(x);
 	if(xprefs != null && xprefs.contains(y))
 		return true;
-	for(ISeq ps = RT.seq(parents.invoke(y)); ps != null; ps = ps.next())
+	for(ISeq ps = RT.seq(parents.invoke(hierarchy, y)); ps != null; ps = ps.next())
 		{
-		if(prefers(x, ps.first()))
+		if(prefers(hierarchy, x, ps.first()))
 			return true;
 		}
-	for(ISeq ps = RT.seq(parents.invoke(x)); ps != null; ps = ps.next())
+	for(ISeq ps = RT.seq(parents.invoke(hierarchy, x)); ps != null; ps = ps.next())
 		{
-		if(prefers(ps.first(), y))
+		if(prefers(hierarchy, ps.first(), y))
 			return true;
 		}
 	return false;
 }
 
-private boolean isA(Object x, Object y) {
-    return RT.booleanCast(isa.invoke(hierarchy.deref(), x, y));
+private boolean isA(Object hierarchy, Object x, Object y) {
+    return RT.booleanCast(isa.invoke(hierarchy, x, y));
 }
 
-private boolean dominates(Object x, Object y) {
-	return prefers(x, y) || isA(x, y);
+private boolean dominates(Object hierarchy, Object x, Object y) {
+	return prefers(hierarchy, x, y) || isA(hierarchy, x, y);
 }
 
 private IPersistentMap resetCache() {
@@ -170,11 +170,11 @@ private IFn findAndCacheBestMethod(Object dispatchVal) {
 		for(Object o : getMethodTable())
 			{
 			Map.Entry e = (Map.Entry) o;
-			if(isA(dispatchVal, e.getKey()))
+			if(isA(ch, dispatchVal, e.getKey()))
 				{
-				if(bestEntry == null || dominates(e.getKey(), bestEntry.getKey()))
+				if(bestEntry == null || dominates(ch, e.getKey(), bestEntry.getKey()))
 					bestEntry = e;
-				if(!dominates(bestEntry.getKey(), e.getKey()))
+				if(!dominates(ch, bestEntry.getKey(), e.getKey()))
 					throw new IllegalArgumentException(
 							String.format(
 									"Multiple methods in multimethod '%s' match dispatch value: %s -> %s and %s, and neither is preferred",
diff --git a/test/clojure/test_clojure/multimethods.clj b/test/clojure/test_clojure/multimethods.clj
index 924b0bcbeb..435f0f64a5 100644
--- a/test/clojure/test_clojure/multimethods.clj
+++ b/test/clojure/test_clojure/multimethods.clj
@@ -203,6 +203,43 @@
  (testing "The prefers method now returns the correct table"
    (is (= {[::rect ::shape] #{[::shape ::rect]}} (prefers bar)))))
 
+(deftest indirect-preferences-mulitmethod-test
+  (testing "Using global hierarchy"
+    (derive ::parent-1 ::grandparent-1)
+    (derive ::parent-2 ::grandparent-2)
+    (derive ::child ::parent-1)
+    (derive ::child ::parent-2)
+    (testing "x should be preferred over y if x is preferred over an ancestor of y"
+      (defmulti indirect-1 keyword)
+      (prefer-method indirect-1 ::parent-1 ::grandparent-2)
+      (defmethod indirect-1 ::parent-1 [_] ::parent-1)
+      (defmethod indirect-1 ::parent-2 [_] ::parent-2)
+      (is (= ::parent-1 (indirect-1 ::child))))
+    (testing "x should be preferred over y if an ancestor of x is preferred over y"
+      (defmulti indirect-2 keyword)
+      (prefer-method indirect-2 ::grandparent-1 ::parent-2)
+      (defmethod indirect-2 ::parent-1 [_] ::parent-1)
+      (defmethod indirect-2 ::parent-2 [_] ::parent-2)
+      (is (= ::parent-1 (indirect-2 ::child)))))
+  (testing "Using custom hierarchy"
+    (def local-h (-> (make-hierarchy)
+                     (derive :parent-1 :grandparent-1)
+                     (derive :parent-2 :grandparent-2)
+                     (derive :child :parent-1)
+                     (derive :child :parent-2)))
+    (testing "x should be preferred over y if x is preferred over an ancestor of y"
+      (defmulti indirect-3 keyword :hierarchy #'local-h)
+      (prefer-method indirect-3 :parent-1 :grandparent-2)
+      (defmethod indirect-3 :parent-1 [_] :parent-1)
+      (defmethod indirect-3 :parent-2 [_] :parent-2)
+      (is (= :parent-1 (indirect-3 :child))))
+    (testing "x should be preferred over y if an ancestor of x is preferred over y"
+      (defmulti indirect-4 keyword :hierarchy #'local-h)
+      (prefer-method indirect-4 :grandparent-1 :parent-2)
+      (defmethod indirect-4 :parent-1 [_] :parent-1)
+      (defmethod indirect-4 :parent-2 [_] :parent-2)
+      (is (= :parent-1 (indirect-4 :child))))))
+
 (deftest remove-all-methods-test
   (testing "Core function remove-all-methods works"
     (defmulti simple1 identity)

From c33a5abca7828843b7018a8aa28e63dd40310f86 Mon Sep 17 00:00:00 2001
From: Jonathan D Johnston 
Date: Thu, 21 Mar 2019 20:59:30 -0400
Subject: [PATCH 47/78] CLJ-2493: Prevent browse-url from hanging when using
 xdg-open (updated)

Signed-off-by: Alex Miller 
---
 src/clj/clojure/java/browse.clj |  2 +-
 src/clj/clojure/java/shell.clj  | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/clj/clojure/java/browse.clj b/src/clj/clojure/java/browse.clj
index 6fcc650756..c416e53832 100644
--- a/src/clj/clojure/java/browse.clj
+++ b/src/clj/clojure/java/browse.clj
@@ -71,6 +71,6 @@
         script (if (= :uninitialized script)
                  (reset! *open-url-script* (open-url-script-val))
                  script)]
-    (or (when script (sh/sh script (str url)) true)
+    (or (when script (sh/launch script (str url)) true)
         (open-url-in-browser url)
         (open-url-in-swing url))))
diff --git a/src/clj/clojure/java/shell.clj b/src/clj/clojure/java/shell.clj
index cb3f90a276..8f167086df 100644
--- a/src/clj/clojure/java/shell.clj
+++ b/src/clj/clojure/java/shell.clj
@@ -127,6 +127,21 @@ collecting its stdout"}
             exit-code (.waitFor proc)]
         {:exit exit-code :out @out :err @err}))))
 
+(defn launch
+  "Same as sh except the I/O channels of the sub-process are ignored.
+
+  Use when you want the sub-process to take an action, but do not want to wait
+  for the I/O channels to close. Example: Launching a browser with xdg-open.
+  "
+  {:added "1.11"}
+  [& args]
+  (let [[cmd opts] (parse-args args)
+        proc (.exec (Runtime/getRuntime)
+               ^"[Ljava.lang.String;" (into-array cmd)
+               (as-env-strings (:env opts))
+               (as-file (:dir opts)))]
+    {:exit (.waitFor proc)}))
+
 (comment
 
 (println (sh "ls" "-l"))
@@ -139,4 +154,9 @@ collecting its stdout"}
 (println (sh "cat" "myimage.png" :out-enc :bytes)) ; reads binary file into bytes[]
 (println (sh "cmd" "/c dir 1>&2"))
 
+(println (launch "touch" "my-test-file"))
+(println (sh "ls" "-l" "my-test-file"))
+(println (launch "rm" "my-test-file"))
+(println (sh "ls" "-l" "my-test-file"))
+
 )

From b962791cbb201e91c29003f2ae1f7cd7a908971f Mon Sep 17 00:00:00 2001
From: Ghadi Shayban 
Date: Fri, 16 Oct 2020 16:13:10 -0400
Subject: [PATCH 48/78] CLJ-2556 complete into's process consistently

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj                  |  6 +++++-
 test/clojure/test_clojure/transducers.clj | 10 ++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 72a4548eb3..30500de3e9 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -6961,7 +6961,11 @@ fails, attempts to require sym's namespace and retries."
        (reduce conj to from)))
   ([to xform from]
      (if (instance? clojure.lang.IEditableCollection to)
-       (with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to))
+       (let [tm (meta to)
+             rf (fn
+                  ([coll] (-> (persistent! coll) (with-meta tm)))
+                  ([coll v] (conj! coll v)))]
+         (transduce xform rf (transient to) from))
        (transduce xform conj to from))))
 
 (defn mapv
diff --git a/test/clojure/test_clojure/transducers.clj b/test/clojure/test_clojure/transducers.clj
index 76a0e978a3..b7a9c665e2 100644
--- a/test/clojure/test_clojure/transducers.clj
+++ b/test/clojure/test_clojure/transducers.clj
@@ -398,3 +398,13 @@
          (sequence (map-indexed vector) [])))
   (is (= [[0 1] [1 2] [2 3] [3 4]]
          (sequence (map-indexed vector) (range 1 5)))))
+
+(deftest test-into+halt-when
+  (is (= :anomaly (into [] (comp (filter some?) (halt-when #{:anomaly}))
+                        [1 2 3 :anomaly 4])))
+  (is (= {:anomaly :oh-no!,
+          :partial-results [1 2]}
+         (into []
+               (halt-when :anomaly #(assoc %2 :partial-results %1))
+               [1 2 {:anomaly :oh-no!} 3 4]))))
+

From c01f10bd8c68bd16c657fe352b206573f9306168 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 21 Oct 2021 22:40:07 -0500
Subject: [PATCH 49/78] CLJ-2665 Modify change for :as-alias to load if :as or
 :use also included

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj              | 31 +++++++++++++--------------
 test/clojure/test_clojure/ns_libs.clj | 12 ++++++-----
 2 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 30500de3e9..055050b530 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -5960,26 +5960,25 @@
         opts (apply hash-map options)
         {:keys [as reload reload-all require use verbose as-alias]} opts
         loaded (contains? @*loaded-libs* lib)
-        load (cond reload-all
-                   load-all
-                   (or reload (not require) (not loaded))
-                   load-one)
         need-ns (or as use)
+        load (cond reload-all load-all
+                   reload load-one
+                   (not loaded) (cond need-ns load-one
+                                      as-alias (fn [lib _need _require] (create-ns lib))
+                                      :else load-one))
+
         filter-opts (select-keys opts '(:exclude :only :rename :refer))
         undefined-on-entry (not (find-ns lib))]
     (binding [*loading-verbosely* (or *loading-verbosely* verbose)]
-      (if as-alias
-        (when (not (find-ns lib))
-          (create-ns lib))
-        (if load
-          (try
-            (load lib need-ns require)
-            (catch Exception e
-              (when undefined-on-entry
-                (remove-ns lib))
-              (throw e)))
-          (throw-if (and need-ns (not (find-ns lib)))
-            "namespace '%s' not found" lib)))
+      (if load
+        (try
+          (load lib need-ns require)
+          (catch Exception e
+            (when undefined-on-entry
+              (remove-ns lib))
+            (throw e)))
+        (throw-if (and need-ns (not (find-ns lib)))
+          "namespace '%s' not found" lib))
       (when (and need-ns *loading-verbosely*)
         (printf "(clojure.core/in-ns '%s)\n" (ns-name *ns*)))
       (when as
diff --git a/test/clojure/test_clojure/ns_libs.clj b/test/clojure/test_clojure/ns_libs.clj
index a9f4f97f71..256f99ae87 100644
--- a/test/clojure/test_clojure/ns_libs.clj
+++ b/test/clojure/test_clojure/ns_libs.clj
@@ -116,16 +116,18 @@
 
   (is (= :not.a.real.ns.foo/baz (read-string "::foo/baz")))
 
-  ;; can use :as-alias in use
-  (use '[dummy.example1 :as-alias e1])
-  (let [aliases (ns-aliases *ns*)]
-    (is (= 'dummy.example1 (ns-name (get aliases 'e1)))))
+  ;; can use :as-alias in use, but load will occur
+  (use '[clojure.walk :as-alias e1])
+  (is (= 'clojure.walk (ns-name (get (ns-aliases *ns*) 'e1))))
+  (is (= :clojure.walk/walk (read-string "::e1/walk")))
 
   ;; can use both :as and :as-alias
   (require '[clojure.set :as n1 :as-alias n2])
   (let [aliases (ns-aliases *ns*)]
     (is (= 'clojure.set (ns-name (get aliases 'n1))))
-    (is (= 'clojure.set (ns-name (get aliases 'n2))))))
+    (is (= 'clojure.set (ns-name (get aliases 'n2))))
+    (is (= (resolve 'n1/union) #'clojure.set/union))
+    (is (= (resolve 'n2/union) #'clojure.set/union))))
 
 (deftest require-as-alias-then-load-later
   ;; alias but don't load

From 4a4a6e7717d411679820c4a3ce735a77aef45cc3 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 2 Dec 2021 13:37:05 -0600
Subject: [PATCH 50/78] CLJ-2611 Disallow XXE by default in clojure.xml/parse

Signed-off-by: Alex Miller 
---
 src/clj/clojure/xml.clj                   | 40 ++++++++++++++++++++---
 test/clojure/test_clojure/clojure_xml.clj | 13 ++++++--
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/clj/clojure/xml.clj b/src/clj/clojure/xml.clj
index 4e4220f265..d892e19279 100644
--- a/src/clj/clojure/xml.clj
+++ b/src/clj/clojure/xml.clj
@@ -72,8 +72,36 @@
            (skippedEntity [name])
            ))))
 
-(defn startparse-sax [s ch]
-  (.. SAXParserFactory (newInstance) (newSAXParser) (parse s ch)))
+(defn sax-parser
+  "Create a new SAXParser"
+  {:added "1.11"}
+  ^SAXParser []
+  (.newSAXParser (SAXParserFactory/newInstance)))
+
+(defn disable-external-entities
+  "Modifies a SAXParser to disable external entity resolution to prevent XXE attacks"
+  {:added "1.11"}
+  ^SAXParser [^SAXParser parser]
+  (let [reader (.getXMLReader parser)]
+    ;; as per https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+    (.setFeature reader "http://apache.org/xml/features/nonvalidating/load-external-dtd" false)
+    (.setFeature reader "http://xml.org/sax/features/external-general-entities", false)
+    (.setFeature reader "http://xml.org/sax/features/external-parameter-entities" false)
+    parser))
+
+(defn startparse-sax
+  "A startparse function suitable for use with clojure.xml/parse.
+  Note that this function is open to XXE entity attacks, see startparse-sax-safe."
+  {:added "1.0"}
+  [s ch]
+  (.parse (sax-parser) s ch))
+
+(defn startparse-sax-safe
+  "A startparse function suitable for use with clojure.xml/parse.
+  External entity resolution is disabled to prevent XXE entity attacks."
+  {:added "1.11"}
+  [s ch]
+  (.parse (disable-external-entities (sax-parser)) s ch))
 
 (defn parse
   "Parses and loads the source s, which can be a File, InputStream or
@@ -81,9 +109,13 @@
   which has the keys :tag, :attrs, and :content. and accessor fns tag,
   attrs, and content. Other parsers can be supplied by passing
   startparse, a fn taking a source and a ContentHandler and returning
-  a parser"
+  a parser.
+
+  Prior to 1.11, used startparse-sax by default. As of 1.11, uses
+  startparse-sax-safe, which disables XXE (XML External Entity)
+  processing. Pass startparse-sax to revert to prior behavior."
   {:added "1.0"}
-  ([s] (parse s startparse-sax))
+  ([s] (parse s startparse-sax-safe))
   ([s startparse]
     (binding [*stack* nil
               *current* (struct element)
diff --git a/test/clojure/test_clojure/clojure_xml.clj b/test/clojure/test_clojure/clojure_xml.clj
index cf7eb9508d..d37962f361 100644
--- a/test/clojure/test_clojure/clojure_xml.clj
+++ b/test/clojure/test_clojure/clojure_xml.clj
@@ -11,9 +11,18 @@
 
 (ns clojure.test-clojure.clojure-xml
   (:use clojure.test)
-  (:require [clojure.xml :as xml]))
-
+  (:require [clojure.xml :as xml])
+  (:import [java.io ByteArrayInputStream]))
 
+(deftest CLJ-2611-avoid-XXE
+  (let [xml-str "
+
+  ]>
+&xxe;"]
+    (is (= {:tag :foo, :attrs nil, :content nil}
+           (with-open [input (ByteArrayInputStream. (.getBytes xml-str))]
+             (xml/parse input))))))
 ; parse
 
 ; emit-element

From e45e47882597359aa2adce9f244ecdba730e6c76 Mon Sep 17 00:00:00 2001
From: Ghadi Shayban 
Date: Thu, 13 Jan 2022 14:27:57 -0600
Subject: [PATCH 51/78] CLJ-2555: clojure.core/iteration

Subsumes CLJ-1906

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj                | 43 +++++++++++++
 test/clojure/test_clojure/sequences.clj | 85 +++++++++++++++++++++++++
 2 files changed, 128 insertions(+)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 055050b530..4db32604a6 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -7783,6 +7783,49 @@ fails, attempts to require sym's namespace and retries."
   (reduce #(proc %2) nil coll)
   nil)
 
+(defn iteration
+  "creates a seqable/reducible given step!,
+   a function of some (opaque continuation data) k
+
+   step! - fn of k/nil to (opaque) 'ret'
+
+   :some? - fn of ret -> truthy, indicating there is a value
+           will not call vf/kf nor continue when false
+   :vf - fn of ret -> v, the values produced by the iteration
+   :kf - fn of ret -> next-k or nil (will not continue)
+   :initk - the first value passed to step!
+
+   vf, kf default to identity, some? defaults to some?, initk defaults to nil
+
+   it is presumed that step! with non-initk is unreproducible/non-idempotent
+   if step! with initk is unreproducible, it is on the consumer to not consume twice"
+  {:added "1.11"}
+  [step! & {:keys [vf kf some? initk]
+            :or {vf identity
+                 kf identity
+                 some? some?
+                 initk nil}}]
+  (reify
+   clojure.lang.Seqable
+   (seq [_]
+        ((fn next [ret]
+           (when (some? ret)
+             (cons (vf ret)
+                   (when-some [k (kf ret)]
+                     (lazy-seq (next (step! k)))))))
+         (step! initk)))
+   clojure.lang.IReduceInit
+   (reduce [_ rf init]
+           (loop [acc init
+                  ret (step! initk)]
+             (if (some? ret)
+               (let [acc (rf acc (vf ret))]
+                 (if (reduced? acc)
+                   @acc
+                   (if-some [k (kf ret)]
+                     (recur acc (step! k))
+                     acc)))
+               acc)))))
 
 (defn tagged-literal?
   "Return true if the value is the data representation of a tagged literal"
diff --git a/test/clojure/test_clojure/sequences.clj b/test/clojure/test_clojure/sequences.clj
index 54d640f72d..96e6775bdd 100644
--- a/test/clojure/test_clojure/sequences.clj
+++ b/test/clojure/test_clojure/sequences.clj
@@ -1384,3 +1384,88 @@
     (when (reversible? coll)
       (is (= true (instance? clojure.lang.IMeta (rseq coll))))
       (is (= {:a true} (meta (with-meta (rseq coll) {:a true})))))))
+
+(deftest test-iteration-opts
+  (let [genstep (fn [steps]
+                  (fn [k] (swap! steps inc) (inc k)))
+        test (fn [expect & iteropts]
+               (is (= expect
+                      (let [nsteps (atom 0)
+                            iter (apply iteration (genstep nsteps) iteropts)
+                            ret (doall (seq iter))]
+                        {:ret ret :steps @nsteps})
+                      (let [nsteps (atom 0)
+                            iter (apply iteration (genstep nsteps) iteropts)
+                            ret (into [] iter)]
+                        {:ret ret :steps @nsteps}))))]
+    (test {:ret [1 2 3 4]
+           :steps 5}
+          :initk 0 :some? #(< % 5))
+    (test {:ret [1 2 3 4 5]
+           :steps 5}
+          :initk 0 :kf (fn [ret] (when (< ret 5) ret)))
+    (test {:ret ["1"]
+           :steps 2}
+          :initk 0 :some? #(< % 2) :vf str))
+
+  ;; kf does not stop on false
+  (let [iter #(iteration (fn [k]
+                           (if (boolean? k)
+                             [10 :boolean]
+                             [k k]))
+                         :vf second
+                         :kf (fn [[k v]]
+                               (cond
+                                 (= k 3) false
+                                 (< k 14) (inc k)))
+                         :initk 0)]
+    (is (= [0 1 2 3 :boolean 11 12 13 14]
+           (into [] (iter))
+           (seq (iter))))))
+
+(deftest test-iteration
+  ;; equivalence to line-seq
+  (let [readme #(java.nio.file.Files/newBufferedReader (.toPath (java.io.File. "readme.txt")))]
+    (is (= (with-open [r (readme)]
+             (vec (iteration (fn [_] (.readLine r)))))
+           (with-open [r (readme)]
+             (doall (line-seq r))))))
+
+  ;; paginated API
+  (let [items 12 pgsize 5
+        src (vec (repeatedly items #(java.util.UUID/randomUUID)))
+        api (fn [tok]
+              (let [tok (or tok 0)]
+                (when (< tok items)
+                  {:tok (+ tok pgsize)
+                   :ret (subvec src tok (min (+ tok pgsize) items))})))]
+    (is (= src
+           (mapcat identity (iteration api :kf :tok :vf :ret))
+           (into [] cat (iteration api :kf :tok :vf :ret)))))
+
+  (let [src [:a :b :c :d :e]
+        api (fn [k]
+              (let [k (or k 0)]
+                (if (< k (count src))
+                  {:item (nth src k)
+                   :k (inc k)})))]
+    (is (= [:a :b :c]
+           (vec (iteration api
+                           :some? (comp #{:a :b :c} :item)
+                           :kf :k
+                           :vf :item))
+           (vec (iteration api
+                           :kf #(some-> % :k #{0 1 2})
+                           :vf :item))))))
+
+(defspec iteration-seq-equals-reduce 100
+  (prop/for-all [initk gen/int
+                 seed gen/int]
+    (let [src (fn []
+                (let [rng (java.util.Random. seed)]
+                  (iteration #(unchecked-add % (.nextLong rng))
+                             :some? (complement #(zero? (mod % 1000)))
+                             :vf str
+                             :initk initk)))]
+      (= (into [] (src))
+         (seq (src))))))
\ No newline at end of file

From 5451cee06b9e31513a19e596e4e155d1f08d2a8d Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 13 Jan 2022 14:38:37 -0600
Subject: [PATCH 52/78] CLJ-2680 Primitive local bindings can have matching
 type hint

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/Compiler.java    | 9 +++++++--
 test/clojure/test_clojure/numbers.clj | 3 +++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index ce16f85a21..cacaeb0f0e 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -6024,9 +6024,14 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr, Assign
 	public LocalBindingExpr(LocalBinding b, Symbol tag)
             {
 		if(b.getPrimitiveType() != null && tag != null)
-			throw new UnsupportedOperationException("Can't type hint a primitive local");
+			if(! b.getPrimitiveType().equals(tagClass(tag)))
+				throw new UnsupportedOperationException("Can't type hint a primitive local with a different type");
+			else
+				this.tag = null;
+		else
+			this.tag = tag;
+
 		this.b = b;
-		this.tag = tag;
 
         this.clearPath = (PathNode)CLEAR_PATH.get();
         this.clearRoot = (PathNode)CLEAR_ROOT.get();
diff --git a/test/clojure/test_clojure/numbers.clj b/test/clojure/test_clojure/numbers.clj
index a6b61605ea..bf822cc947 100644
--- a/test/clojure/test_clojure/numbers.clj
+++ b/test/clojure/test_clojure/numbers.clj
@@ -184,6 +184,9 @@
                        (catch RuntimeException e :error)))]
         (is (= vals (map wrapped inputs)))))))
 
+(deftest test-prim-with-matching-hint
+  (is (= 1 (let [x 1.2] (Math/round ^double x)))))
+
 ;; *** Functions ***
 
 (defonce DELTA 1e-12)

From 2b3ba822815981e7f76907a3b75e9ecc428f7656 Mon Sep 17 00:00:00 2001
From: Ghadi Shayban 
Date: Thu, 20 Jan 2022 10:54:35 -0600
Subject: [PATCH 53/78] CLJ-2690 Clarify iteration docstring, rename args

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core.clj                | 41 +++++++++++++------------
 test/clojure/test_clojure/sequences.clj |  8 ++---
 2 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 4db32604a6..42abb7f00a 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -7784,46 +7784,49 @@ fails, attempts to require sym's namespace and retries."
   nil)
 
 (defn iteration
-  "creates a seqable/reducible given step!,
-   a function of some (opaque continuation data) k
+  "Creates a seqable/reducible via repeated calls to step,
+  a function of some (continuation token) 'k'. The first call to step
+  will be passed initk, returning 'ret'. Iff (somef ret) is true,
+  (vf ret) will be included in the iteration, else iteration will
+  terminate and vf/kf will not be called. If (kf ret) is non-nil it
+  will be passed to the next step call, else iteration will terminate.
 
-   step! - fn of k/nil to (opaque) 'ret'
+  This can be used e.g. to consume APIs that return paginated or batched data.
 
-   :some? - fn of ret -> truthy, indicating there is a value
-           will not call vf/kf nor continue when false
-   :vf - fn of ret -> v, the values produced by the iteration
-   :kf - fn of ret -> next-k or nil (will not continue)
-   :initk - the first value passed to step!
+   step - (possibly impure) fn of 'k' -> 'ret'
 
-   vf, kf default to identity, some? defaults to some?, initk defaults to nil
+   :somef - fn of 'ret' -> logical true/false, default 'some?'
+   :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity'
+   :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity'
+   :initk - the first value passed to step, default 'nil'
 
-   it is presumed that step! with non-initk is unreproducible/non-idempotent
-   if step! with initk is unreproducible, it is on the consumer to not consume twice"
+  It is presumed that step with non-initk is unreproducible/non-idempotent.
+  If step with initk is unreproducible it is on the consumer to not consume twice."
   {:added "1.11"}
-  [step! & {:keys [vf kf some? initk]
+  [step & {:keys [somef vf kf initk]
             :or {vf identity
                  kf identity
-                 some? some?
+                 somef some?
                  initk nil}}]
   (reify
    clojure.lang.Seqable
    (seq [_]
         ((fn next [ret]
-           (when (some? ret)
+           (when (somef ret)
              (cons (vf ret)
                    (when-some [k (kf ret)]
-                     (lazy-seq (next (step! k)))))))
-         (step! initk)))
+                     (lazy-seq (next (step k)))))))
+         (step initk)))
    clojure.lang.IReduceInit
    (reduce [_ rf init]
            (loop [acc init
-                  ret (step! initk)]
-             (if (some? ret)
+                  ret (step initk)]
+             (if (somef ret)
                (let [acc (rf acc (vf ret))]
                  (if (reduced? acc)
                    @acc
                    (if-some [k (kf ret)]
-                     (recur acc (step! k))
+                     (recur acc (step k))
                      acc)))
                acc)))))
 
diff --git a/test/clojure/test_clojure/sequences.clj b/test/clojure/test_clojure/sequences.clj
index 96e6775bdd..1fc93cd8ce 100644
--- a/test/clojure/test_clojure/sequences.clj
+++ b/test/clojure/test_clojure/sequences.clj
@@ -1400,13 +1400,13 @@
                         {:ret ret :steps @nsteps}))))]
     (test {:ret [1 2 3 4]
            :steps 5}
-          :initk 0 :some? #(< % 5))
+          :initk 0 :somef #(< % 5))
     (test {:ret [1 2 3 4 5]
            :steps 5}
           :initk 0 :kf (fn [ret] (when (< ret 5) ret)))
     (test {:ret ["1"]
            :steps 2}
-          :initk 0 :some? #(< % 2) :vf str))
+          :initk 0 :somef #(< % 2) :vf str))
 
   ;; kf does not stop on false
   (let [iter #(iteration (fn [k]
@@ -1451,7 +1451,7 @@
                    :k (inc k)})))]
     (is (= [:a :b :c]
            (vec (iteration api
-                           :some? (comp #{:a :b :c} :item)
+                           :somef (comp #{:a :b :c} :item)
                            :kf :k
                            :vf :item))
            (vec (iteration api
@@ -1464,7 +1464,7 @@
     (let [src (fn []
                 (let [rng (java.util.Random. seed)]
                   (iteration #(unchecked-add % (.nextLong rng))
-                             :some? (complement #(zero? (mod % 1000)))
+                             :somef (complement #(zero? (mod % 1000)))
                              :vf str
                              :initk initk)))]
       (= (into [] (src))

From 326366d11923620f6815cfd149300bb48da01593 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Wed, 19 Jan 2022 12:55:12 -0600
Subject: [PATCH 54/78] CLJ-2689 Provide more tolerance for inexact floating
 point math tests

Signed-off-by: Alex Miller 
---
 test/clojure/test_clojure/math.clj | 44 +++++++++++++++++-------------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/test/clojure/test_clojure/math.clj b/test/clojure/test_clojure/math.clj
index 63975e7505..4520b41b2b 100644
--- a/test/clojure/test_clojure/math.clj
+++ b/test/clojure/test_clojure/math.clj
@@ -21,20 +21,26 @@
   [^double d]
   (and (zero? d) (not (< (Double/compare d 0.0) 0))))
 
+(defn ulp=
+  "Tests that y = x +/- m*ulp(x)"
+  [x y ^double m]
+  (let [mu (* (m/ulp x) m)]
+    (<= (- x mu) y (+ x mu))))
+
 (deftest test-sin
   (is (NaN? (m/sin ##NaN)))
   (is (NaN? (m/sin ##-Inf)))
   (is (NaN? (m/sin ##Inf)))
   (is (pos-zero? (m/sin 0.0)))
   (is (neg-zero? (m/sin -0.0)))
-  (is (= (m/sin m/PI) (- (m/sin (- m/PI))))))
+  (is (ulp= (m/sin m/PI) (- (m/sin (- m/PI))) 1)))
 
 (deftest test-cos
   (is (NaN? (m/cos ##NaN)))
   (is (NaN? (m/cos ##-Inf)))
   (is (NaN? (m/cos ##Inf)))
   (is (= 1.0 (m/cos 0.0) (m/cos -0.0)))
-  (is (= (m/cos m/PI) (m/cos (- m/PI)))))
+  (is (ulp= (m/cos m/PI) (m/cos (- m/PI)) 1)))
 
 (deftest test-tan
   (is (NaN? (m/tan ##NaN)))
@@ -42,7 +48,7 @@
   (is (NaN? (m/tan ##Inf)))
   (is (pos-zero? (m/tan 0.0)))
   (is (neg-zero? (m/tan -0.0)))
-  (is (= (- (m/tan m/PI)) (m/tan (- m/PI)))))
+  (is (ulp= (- (m/tan m/PI)) (m/tan (- m/PI)) 1)))
 
 (deftest test-asin
   (is (NaN? (m/asin ##NaN)))
@@ -54,45 +60,45 @@
   (is (NaN? (m/acos ##NaN)))
   (is (NaN? (m/acos -2.0)))
   (is (NaN? (m/acos 2.0)))
-  (is (= m/PI (* 2 (m/acos 0.0)))))
+  (is (ulp= (* 2 (m/acos 0.0)) m/PI 1)))
 
 (deftest test-atan
   (is (NaN? (m/atan ##NaN)))
   (is (pos-zero? (m/atan 0.0)))
   (is (neg-zero? (m/atan -0.0)))
-  (is (= 0.7853981633974483 (m/atan 1))))
+  (is (ulp= (m/atan 1) 0.7853981633974483 1)))
 
 (deftest test-radians-degrees-roundtrip
   (doseq [d (range 0.0 360.0 5.0)]
-    (is (= (m/round d) (m/round (-> d m/to-radians m/to-degrees))))))
+    (is (ulp= (m/round d) (m/round (-> d m/to-radians m/to-degrees)) 1))))
 
 (deftest test-exp
   (is (NaN? (m/exp ##NaN)))
   (is (= ##Inf (m/exp ##Inf)))
   (is (pos-zero? (m/exp ##-Inf)))
-  (is (= 1.0 (m/exp 0.0)))
-  (is (= m/E (m/exp 1))))
+  (is (ulp= (m/exp 0.0) 1.0 1))
+  (is (ulp= (m/exp 1) m/E 1)))
 
 (deftest test-log
   (is (NaN? (m/log ##NaN)))
   (is (NaN? (m/log -1.0)))
   (is (= ##Inf (m/log ##Inf)))
   (is (= ##-Inf (m/log 0.0)))
-  (is (= 1.0 (m/log m/E))))
+  (is (ulp= (m/log m/E) 1.0 1)))
 
 (deftest test-log10
   (is (NaN? (m/log10 ##NaN)))
   (is (NaN? (m/log10 -1.0)))
   (is (= ##Inf (m/log10 ##Inf)))
   (is (= ##-Inf (m/log10 0.0)))
-  (is (= 1.0 (m/log10 10))))
+  (is (ulp= (m/log10 10) 1.0 1)))
 
 (deftest test-sqrt
   (is (NaN? (m/sqrt ##NaN)))
   (is (NaN? (m/sqrt -1.0)))
   (is (= ##Inf (m/sqrt ##Inf)))
   (is (pos-zero? (m/sqrt 0)))
-  (is (= 2.0 (m/sqrt 4.0))))
+  (is (= (m/sqrt 4.0) 2.0)))
 
 (deftest test-cbrt
   (is (NaN? (m/cbrt ##NaN)))
@@ -133,14 +139,14 @@
   (is (NaN? (m/atan2 1.0 ##NaN)))
   (is (pos-zero? (m/atan2 0.0 1.0)))
   (is (neg-zero? (m/atan2 -0.0 1.0)))
-  (is (= m/PI (m/atan2 0.0 -1.0)))
-  (is (= (- m/PI) (m/atan2 -0.0 -1.0)))
-  (is (= m/PI (* 2.0 (m/atan2 1.0 0.0))))
-  (is (= m/PI (* -2.0 (m/atan2 -1.0 0.0))))
-  (is (= m/PI (* 4.0 (m/atan2 ##Inf ##Inf))))
-  (is (= m/PI (/ (* 4.0 (m/atan2 ##Inf ##-Inf)) 3.0)))
-  (is (= m/PI (* -4.0 (m/atan2 ##-Inf ##Inf))))
-  (is (= m/PI (/ (* -4.0 (m/atan2 ##-Inf ##-Inf)) 3.0))))
+  (is (ulp= (m/atan2 0.0 -1.0) m/PI 2))
+  (is (ulp= (m/atan2 -0.0 -1.0) (- m/PI) 2))
+  (is (ulp= (* 2.0 (m/atan2 1.0 0.0)) m/PI 2))
+  (is (ulp= (* -2.0 (m/atan2 -1.0 0.0)) m/PI 2))
+  (is (ulp= (* 4.0 (m/atan2 ##Inf ##Inf)) m/PI 2))
+  (is (ulp= (/ (* 4.0 (m/atan2 ##Inf ##-Inf)) 3.0) m/PI 2))
+  (is (ulp= (* -4.0 (m/atan2 ##-Inf ##Inf)) m/PI 2))
+  (is (ulp= (/ (* -4.0 (m/atan2 ##-Inf ##-Inf)) 3.0) m/PI 2)))
 
 (deftest test-pow
   (is (= 1.0 (m/pow 4.0 0.0)))

From da0b9574017918deede6d2a15f386a7cc1b70a2c Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 20 Jan 2022 16:13:26 -0600
Subject: [PATCH 55/78] CLJ-2685 Fix iteration generative test comparison

Signed-off-by: Alex Miller 
---
 test/clojure/test_clojure/sequences.clj | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/clojure/test_clojure/sequences.clj b/test/clojure/test_clojure/sequences.clj
index 1fc93cd8ce..4eb99e7860 100644
--- a/test/clojure/test_clojure/sequences.clj
+++ b/test/clojure/test_clojure/sequences.clj
@@ -988,7 +988,7 @@
       {} {:a 1 :b 2}
       #{} #{1 2} ))
 
-(defspec longrange-equals-range 100
+(defspec longrange-equals-range 1000
   (prop/for-all [start gen/int
                  end gen/int
                  step gen/s-pos-int]
@@ -1458,7 +1458,7 @@
                            :kf #(some-> % :k #{0 1 2})
                            :vf :item))))))
 
-(defspec iteration-seq-equals-reduce 100
+(defspec iteration-seq-equals-reduce 1000
   (prop/for-all [initk gen/int
                  seed gen/int]
     (let [src (fn []
@@ -1468,4 +1468,4 @@
                              :vf str
                              :initk initk)))]
       (= (into [] (src))
-         (seq (src))))))
\ No newline at end of file
+         (into [] (seq (src)))))))

From 027d8ff2859442b222bf9cfa4c1be45567b788eb Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Wed, 2 Feb 2022 14:43:41 -0600
Subject: [PATCH 56/78] Revert "CLJ-2493: Prevent browse-url from hanging when
 using xdg-open (updated)"

This reverts commit c33a5abca7828843b7018a8aa28e63dd40310f86.
---
 src/clj/clojure/java/browse.clj |  2 +-
 src/clj/clojure/java/shell.clj  | 20 --------------------
 2 files changed, 1 insertion(+), 21 deletions(-)

diff --git a/src/clj/clojure/java/browse.clj b/src/clj/clojure/java/browse.clj
index c416e53832..6fcc650756 100644
--- a/src/clj/clojure/java/browse.clj
+++ b/src/clj/clojure/java/browse.clj
@@ -71,6 +71,6 @@
         script (if (= :uninitialized script)
                  (reset! *open-url-script* (open-url-script-val))
                  script)]
-    (or (when script (sh/launch script (str url)) true)
+    (or (when script (sh/sh script (str url)) true)
         (open-url-in-browser url)
         (open-url-in-swing url))))
diff --git a/src/clj/clojure/java/shell.clj b/src/clj/clojure/java/shell.clj
index 8f167086df..cb3f90a276 100644
--- a/src/clj/clojure/java/shell.clj
+++ b/src/clj/clojure/java/shell.clj
@@ -127,21 +127,6 @@ collecting its stdout"}
             exit-code (.waitFor proc)]
         {:exit exit-code :out @out :err @err}))))
 
-(defn launch
-  "Same as sh except the I/O channels of the sub-process are ignored.
-
-  Use when you want the sub-process to take an action, but do not want to wait
-  for the I/O channels to close. Example: Launching a browser with xdg-open.
-  "
-  {:added "1.11"}
-  [& args]
-  (let [[cmd opts] (parse-args args)
-        proc (.exec (Runtime/getRuntime)
-               ^"[Ljava.lang.String;" (into-array cmd)
-               (as-env-strings (:env opts))
-               (as-file (:dir opts)))]
-    {:exit (.waitFor proc)}))
-
 (comment
 
 (println (sh "ls" "-l"))
@@ -154,9 +139,4 @@ collecting its stdout"}
 (println (sh "cat" "myimage.png" :out-enc :bytes)) ; reads binary file into bytes[]
 (println (sh "cmd" "/c dir 1>&2"))
 
-(println (launch "touch" "my-test-file"))
-(println (sh "ls" "-l" "my-test-file"))
-(println (launch "rm" "my-test-file"))
-(println (sh "ls" "-l" "my-test-file"))
-
 )

From 19e3a2708def5ffb7f2be030d8e8e895464ce2d2 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 25 Jan 2022 12:02:09 -0600
Subject: [PATCH 57/78] CLJ-2493 - Prevent browse-url from hanging when using
 xdg-open

Signed-off-by: Alex Miller 
---
 src/clj/clojure/java/browse.clj | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/java/browse.clj b/src/clj/clojure/java/browse.clj
index 6fcc650756..6a16ce37db 100644
--- a/src/clj/clojure/java/browse.clj
+++ b/src/clj/clojure/java/browse.clj
@@ -12,7 +12,9 @@
   clojure.java.browse
   (:require [clojure.java.shell :as sh]
             [clojure.string :as str])
-  (:import (java.net URI)))
+  (:import (java.io File)
+           (java.net URI)
+           (java.lang ProcessBuilder ProcessBuilder$Redirect)))
 
 (defn- macosx? []
   (-> "os.name" System/getProperty .toLowerCase
@@ -71,6 +73,16 @@
         script (if (= :uninitialized script)
                  (reset! *open-url-script* (open-url-script-val))
                  script)]
-    (or (when script (sh/sh script (str url)) true)
+    (or (when script
+          (try
+            (let [command [script (str url)]
+                  null-file (File. (if (.startsWith (System/getProperty "os.name") "Windows") "NUL" "/dev/null"))
+                  pb (doto (ProcessBuilder. ^java.util.List command)
+                       ;; emulate ProcessBuilder.Redirect.DISCARD added in Java 9
+                       (.redirectOutput null-file)
+                       (.redirectError null-file))]
+              (.start pb) ;; do not wait for the process
+              true)
+            (catch Throwable _ false)))
         (open-url-in-browser url)
         (open-url-in-swing url))))

From 4a9ce390519c41eae100954378937eb220a81dc0 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 25 Jan 2022 21:03:58 -0600
Subject: [PATCH 58/78] CLJ-2529 Set exception phase for runtime exceptions
 caught in Compiler.load()

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/Compiler.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index cacaeb0f0e..12cf1e5623 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -7662,7 +7662,7 @@ public static Object load(Reader rdr, String sourcePath, String sourceName) {
 	catch(Throwable e)
 		{
 		if(!(e instanceof CompilerException))
-			throw new CompilerException(sourcePath, (Integer) LINE_BEFORE.deref(), (Integer) COLUMN_BEFORE.deref(), e);
+			throw new CompilerException(sourcePath, (Integer) LINE_BEFORE.deref(), (Integer) COLUMN_BEFORE.deref(), null, CompilerException.PHASE_EXECUTION, e);
 		else
 			throw (CompilerException) e;
 		}

From fc98f92c76254c5a6306debaf0f9df28c3bb3646 Mon Sep 17 00:00:00 2001
From: Fogus 
Date: Tue, 1 Feb 2022 11:34:18 -0500
Subject: [PATCH 59/78] CLJ-2620: io-prepl now calls valf on exeception data in
 the case where an exception occurs in the :print-eval-result phase

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core/server.clj | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/clj/clojure/core/server.clj b/src/clj/clojure/core/server.clj
index 48377d4127..3cda4d1f74 100644
--- a/src/clj/clojure/core/server.clj
+++ b/src/clj/clojure/core/server.clj
@@ -288,7 +288,7 @@
                         (try
                           (assoc m :val (valf (:val m)))
                           (catch Throwable ex
-                            (assoc m :val (ex->data ex :print-eval-result)
+                            (assoc m :val (valf (ex->data ex :print-eval-result))
                                      :exception true)))
                         m))))))))
 

From 8957a93099fc506c3b24ed5739bf9e2fc1811bef Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 20 Jan 2022 21:18:39 -0600
Subject: [PATCH 60/78] CLJ-1180 Resolve classname for tag metadata on
 defprotocol

Signed-off-by: Alex Miller 
---
 src/clj/clojure/core_deftype.clj              | 10 +++++-
 test/clojure/test_clojure/protocols.clj       | 35 +++++++++++++++----
 .../test_clojure/protocols/examples.clj       |  2 ++
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 7906ccbe35..c2babab291 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -652,7 +652,15 @@
             [opts sigs]))
         sigs (when sigs
                (reduce1 (fn [m s]
-                          (let [name-meta (meta (first s))
+                          (let [tag-to-class (fn [tag]
+                                               (if-let [c (and (instance? clojure.lang.Symbol tag)
+                                                            (= (.indexOf (.getName ^clojure.lang.Symbol tag) ".") -1)
+                                                            (not (contains? '#{int long float double char short byte boolean void
+                                                                               ints longs floats doubles chars shorts bytes booleans objects} tag))
+                                                            (resolve tag))]
+                                                 (symbol (.getName c))
+                                                 tag))
+                                name-meta (update-in (meta (first s)) [:tag] tag-to-class)
                                 mname (with-meta (first s) nil)
                                 [arglists doc]
                                 (loop [as [] rs (rest s)]
diff --git a/test/clojure/test_clojure/protocols.clj b/test/clojure/test_clojure/protocols.clj
index ff556dcaed..4e951449bb 100644
--- a/test/clojure/test_clojure/protocols.clj
+++ b/test/clojure/test_clojure/protocols.clj
@@ -47,13 +47,13 @@
 (deftest protocols-test
   (testing "protocol fns have useful metadata"
     (let [common-meta {:ns (find-ns 'clojure.test-clojure.protocols.examples)
-                       :protocol #'ExampleProtocol}]
-      (are [m f] (= (merge (quote m) common-meta)
+                       :protocol #'ExampleProtocol :tag nil}]
+      (are [m f] (= (merge common-meta m)
                     (meta (var f)))
-           {:name foo :arglists ([a]) :doc "method with one arg"} foo
-           {:name bar :arglists ([a b]) :doc "method with two args"} bar
-           {:name baz :arglists ([a] [a b]) :doc "method with multiple arities" :tag String} baz
-           {:name with-quux :arglists ([a]) :doc "method name with a hyphen"} with-quux)))
+           {:name 'foo :arglists '([a]) :doc "method with one arg"} foo
+           {:name 'bar :arglists '([a b]) :doc "method with two args"} bar
+           {:name 'baz :arglists '([a] [a b]) :doc "method with multiple arities" :tag 'java.lang.String} baz
+           {:name 'with-quux :arglists '([a]) :doc "method name with a hyphen"} with-quux)))
   (testing "protocol fns throw IllegalArgumentException if no impl matches"
     (is (thrown-with-msg?
           IllegalArgumentException
@@ -682,3 +682,26 @@
          (reduce-kv #(assoc %1 %3 %2)
                     {}
                     (seq {:a 1 :b 2})))))
+
+(defn aget-long-hinted ^long [x] (aget (longs-hinted x) 0))
+
+(deftest test-longs-hinted-proto
+  (is (= 1
+        (aget-long-hinted
+          (reify LongsHintedProto
+            (longs-hinted [_] (long-array [1])))))))
+
+;; CLJ-1180 - resolve type hints in protocol methods
+
+(import 'clojure.lang.ISeq)
+(defprotocol P
+  (^ISeq f [_]))
+(ns clojure.test-clojure.protocols.other
+  (:use clojure.test))
+(defn cf [val]
+  (let [aseq (clojure.test-clojure.protocols/f val)]
+    (count aseq)))
+(extend-protocol clojure.test-clojure.protocols/P String
+  (f [s] (seq s)))
+(deftest test-resolve-type-hints-in-protocol-methods
+  (is (= 4 (clojure.test-clojure.protocols/f "test"))))
diff --git a/test/clojure/test_clojure/protocols/examples.clj b/test/clojure/test_clojure/protocols/examples.clj
index 9d962d5651..0c247eab04 100644
--- a/test/clojure/test_clojure/protocols/examples.clj
+++ b/test/clojure/test_clojure/protocols/examples.clj
@@ -17,3 +17,5 @@
   (hinted [^int i])
   (hinted [^String s]))
 
+(defprotocol LongsHintedProto
+  (^longs longs-hinted [_]))

From 658693f6cf97e6ab0ff789e096c9eb6654e4d3ab Mon Sep 17 00:00:00 2001
From: Ambrose Bonnaire-Sergeant 
Date: Tue, 25 Jan 2022 12:34:24 -0600
Subject: [PATCH 61/78] CLJ-1973: sort proxy methods for reproducibility

Comparator sorts methods by arity then name/param-types/return-types on clashes.

Signed-off-by: Alex Miller 
---
 build.xml                                    |  1 +
 src/clj/clojure/core_proxy.clj               | 15 +++++---
 test/clojure/test_clojure/java_interop.clj   | 38 ++++++++++++++++++--
 test/clojure/test_clojure/proxy/examples.clj | 30 ++++++++++++++++
 4 files changed, 77 insertions(+), 7 deletions(-)
 create mode 100644 test/clojure/test_clojure/proxy/examples.clj

diff --git a/build.xml b/build.xml
index 6796b3d986..34fd65b2c6 100644
--- a/build.xml
+++ b/build.xml
@@ -105,6 +105,7 @@
         
       
       
+      
       
       
       
diff --git a/src/clj/clojure/core_proxy.clj b/src/clj/clojure/core_proxy.clj
index c7f35774e6..46f7b4b868 100644
--- a/src/clj/clojure/core_proxy.clj
+++ b/src/clj/clojure/core_proxy.clj
@@ -241,12 +241,17 @@
           mb (map #(vector (%1 %2) (vals (dissoc %1 %2))) mgroups rtypes)
           bridge? (reduce1 into1 #{} (map second mb))
           ifaces-meths (remove bridge? (vals ifaces-meths))
-          mm (remove bridge? (vals mm))]
+          mm (remove bridge? (vals mm))
+          reflect-Method-keyfn (fn [meth]
+                                 (let [[name param-types ^Class return-type] (method-sig meth)]
+                                   (-> [name]
+                                       (into1 (map #(.getName ^Class %) param-types))
+                                       (conj (.getName return-type)))))]
                                         ;add methods matching supers', if no mapping -> call super
-      (doseq [[^java.lang.reflect.Method dest bridges] mb
-              ^java.lang.reflect.Method meth bridges]
+      (doseq [[^java.lang.reflect.Method dest bridges] (sort-by (comp reflect-Method-keyfn first) mb)
+              ^java.lang.reflect.Method meth (sort-by reflect-Method-keyfn bridges)]
           (gen-bridge meth dest))
-      (doseq [^java.lang.reflect.Method meth mm]
+      (doseq [^java.lang.reflect.Method meth (sort-by reflect-Method-keyfn mm)]
           (gen-method meth 
                       (fn [^GeneratorAdapter gen ^Method m]
                           (. gen (loadThis))
@@ -259,7 +264,7 @@
                                                 (. m (getDescriptor)))))))
       
                                         ;add methods matching interfaces', if no mapping -> throw
-      (doseq [^java.lang.reflect.Method meth ifaces-meths]
+      (doseq [^java.lang.reflect.Method meth (sort-by reflect-Method-keyfn ifaces-meths)]
                 (gen-method meth 
                             (fn [^GeneratorAdapter gen ^Method m]
                                 (. gen (throwException ex-type (. m (getName))))))))
diff --git a/test/clojure/test_clojure/java_interop.clj b/test/clojure/test_clojure/java_interop.clj
index cb21064b25..4925284cc2 100644
--- a/test/clojure/test_clojure/java_interop.clj
+++ b/test/clojure/test_clojure/java_interop.clj
@@ -11,8 +11,11 @@
 
 (ns clojure.test-clojure.java-interop
   (:use clojure.test)
-  (:require [clojure.inspector]
-            [clojure.set :as set])
+  (:require [clojure.data :as data]
+            [clojure.inspector]
+            [clojure.pprint :as pp]
+            [clojure.set :as set]
+            [clojure.test-clojure.proxy.examples :as proxy-examples])
   (:import java.util.Base64
            (java.util.concurrent.atomic AtomicLong AtomicInteger)))
 
@@ -176,6 +179,37 @@
             str)
         "chain chain chain")))
 
+;https://clojure.atlassian.net/browse/CLJ-1973
+(deftest test-proxy-method-order
+  (let [class-reader (clojure.asm.ClassReader. proxy-examples/proxy1-class-name)
+        method-order (atom [])
+        method-visitor (proxy [clojure.asm.ClassVisitor] [clojure.asm.Opcodes/ASM4 nil]
+                         (visitMethod [access name descriptor signature exceptions]
+                           (swap! method-order conj {:name name :descriptor descriptor})
+                           nil))
+        _ (.accept class-reader method-visitor 0)
+        expected [{:name "", :descriptor "()V"}
+                  {:name "__initClojureFnMappings", :descriptor "(Lclojure/lang/IPersistentMap;)V"}
+                  {:name "__updateClojureFnMappings", :descriptor "(Lclojure/lang/IPersistentMap;)V"}
+                  {:name "__getClojureFnMappings", :descriptor "()Lclojure/lang/IPersistentMap;"}
+                  {:name "clone", :descriptor "()Ljava/lang/Object;"}
+                  {:name "hashCode", :descriptor "()I"}
+                  {:name "toString", :descriptor "()Ljava/lang/String;"}
+                  {:name "equals", :descriptor "(Ljava/lang/Object;)Z"}
+                  {:name "a", :descriptor "(Ljava/io/File;)Z"}
+                  {:name "a", :descriptor "(Ljava/lang/Boolean;)Ljava/lang/Object;"}
+                  {:name "a", :descriptor "(Ljava/lang/Runnable;)Z"}
+                  {:name "a", :descriptor "(Ljava/lang/String;)I"}
+                  {:name "b", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
+                  {:name "c", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
+                  {:name "d", :descriptor "(Ljava/lang/String;)Ljava/lang/Object;"}
+                  {:name "a", :descriptor "(Ljava/lang/Boolean;Ljava/lang/String;)I"}
+                  {:name "a", :descriptor "(Ljava/lang/String;Ljava/io/File;)Z"}
+                  {:name "a", :descriptor "(Ljava/lang/String;Ljava/lang/Runnable;)Z"}
+                  {:name "a", :descriptor "(Ljava/lang/String;Ljava/lang/String;)I"}]
+        actual @method-order]
+    (is (= expected actual)
+        (with-out-str (pp/pprint (data/diff expected actual))))))
 
 ;; serialized-proxy can be regenerated using a modified version of
 ;; Clojure with the proxy serialization prohibition disabled and the
diff --git a/test/clojure/test_clojure/proxy/examples.clj b/test/clojure/test_clojure/proxy/examples.clj
new file mode 100644
index 0000000000..b98042320f
--- /dev/null
+++ b/test/clojure/test_clojure/proxy/examples.clj
@@ -0,0 +1,30 @@
+;   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+(ns ^{:doc "Test proxy classes that are AOT-compiled for the tests in
+           clojure.test-clojure.java-interop."
+      :author "Ambrose Bonnaire-Sergeant"}
+  clojure.test-clojure.proxy.examples)
+
+(definterface A
+  (^int a [^String x])
+  (^boolean a [^java.io.File x])
+  (^boolean a [^Runnable x])
+  (a [^Boolean x])
+  (^int a [^Boolean x ^String y])
+  (^int a [^String x ^String y])
+  (^boolean a [^String x ^java.io.File y])
+  (^boolean a [^String x ^Runnable y])
+  (b [^String x])
+  (c [^String x])
+  (d [^String x]))
+
+(def ^String proxy1-class-name
+  (-> (proxy [A] [])
+      class
+      .getName))

From 16c91f256fd843687be99b4e3fe2e9af12f5428a Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Wed, 2 Feb 2022 15:07:32 -0600
Subject: [PATCH 62/78] [maven-release-plugin] prepare release
 clojure-1.11.0-beta1

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 59159805a1..4be09160a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-master-SNAPSHOT
+  1.11.0-beta1
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.0-beta1
   
 
   

From 84811650bb33846c7212f391468f9661819b906b Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Wed, 2 Feb 2022 15:07:32 -0600
Subject: [PATCH 63/78] [maven-release-plugin] prepare for next development
 iteration

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4be09160a6..59159805a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-beta1
+  1.11.0-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.0-beta1
+    HEAD
   
 
   

From 3fbdffadabbc36436525a0183f2b3c8aca8648a3 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Tue, 15 Feb 2022 10:52:35 -0600
Subject: [PATCH 64/78] Changelog updates for 1.11

Signed-off-by: Alex Miller 
---
 changes.md | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/changes.md b/changes.md
index 4df7e28540..46b45cbda1 100644
--- a/changes.md
+++ b/changes.md
@@ -1,5 +1,164 @@
 
 
+# Changes to Clojure in Version 1.11.0
+
+## 1 Compatibility
+
+### 1.1 Security
+
+Because XML external entity (XXE) attacks can be used to disclose local files using file schemes or relative paths in the system identifier, `clojure.xml/parse` now disables external entity processing by default.
+
+See: https://owasp.org/www-community/vulnerabilities/XML_External_Entity_(XXE)_Processing
+
+This change disables the following SAX parser features:
+
+* `http://apache.org/xml/features/nonvalidating/load-external-dtd`
+* `http://xml.org/sax/features/external-general-entities`
+* `http://xml.org/sax/features/external-parameter-entities`
+
+If you rely on these features, modify your calls to `clojure.xml/parse` to explicitly
+supply `startparse-sax` function as the final argument: 
+`(clojure.xml/parse the-string clojure.xml/startparse-sax)`
+This modification also works on prior Clojure versions.
+
+* [CLJ-2611](http://dev.clojure.org/jira/browse/CLJ-2611) clojure.xml now disables XXE processing by default
+
+### 1.2 Dependencies
+
+Updated dependencies:
+
+* spec.alpha dependency to 0.3.218 - [changes](https://github.com/clojure/spec.alpha/blob/master/CHANGES.md)
+* core.specs.alpha dependency to 0.2.62 - [changes](https://github.com/clojure/core.specs.alpha/blob/master/CHANGES.md)
+
+## 2 Features
+
+### 2.1 Keyword argument functions take a trailing map
+
+Keyword arguments are optional trailing variadic arguments of the form *akey aval bkey bval...​*.
+In Clojure 1.11, functions taking keyword arguments can now be passed a map instead of or in addition
+to and following the key/value pairs. When a lone map is passed, it is used for destructuring, else
+a trailing map is added to the key/value pair map by `conj`.
+
+Also see: https://clojure.org/news/2021/03/18/apis-serving-people-and-programs
+
+* [CLJ-2603](https://clojure.atlassian.net/browse/CLJ-2603) Clojure keyword argument functions now also accept a map
+
+### 2.2 `:as-alias` in `require`
+
+Spec (and other libs) rely on qualified keywords as spec names.
+Namespace aliasing in `ns` makes long names shorter but required namespaces to be loadable.
+This change adds `:as-alias` to `require`, which is like `:as` but does not require the namespace to load.
+
+* [CLJ-2123](https://clojure.atlassian.net/browse/CLJ-2123) Add :as-alias option to require like :as but not load
+* [CLJ-2665](https://clojure.atlassian.net/browse/CLJ-2665) Fix require with :as and :as-alias to load
+
+## 3 New functions and namespaces
+
+### 3.1 clojure.math and numeric helper functions
+
+Added a new clojure.math namespace which provides wrappers for the functions available in java.lang.Math.
+These functions are narrowed to only `long` and `double` overloads and provide primitive support without reflection.
+
+In addition, the following functions were added to clojure.core:
+
+* `abs` - absolute value in optimized form for all Clojure numeric types (long, double, ratio, bigint, bigdecimal)
+* `NaN?` - predicate for doubles to check whether "not a number"
+* `infinite?` - predicate for doubles to check whether positive or negative infinity
+
+* [CLJ-2668](https://clojure.atlassian.net/browse/CLJ-2668) Add NaN? and infinite? predicates
+* [CLJ-2664](https://clojure.atlassian.net/browse/CLJ-2664) Add clojure.java.math namespace, wrappers for java.lang.Math
+* [CLJ-2673](https://clojure.atlassian.net/browse/CLJ-2673) Add `abs`, and update `min` and `max` to use Math impls when possible
+* [CLJ-2677](https://clojure.atlassian.net/browse/CLJ-2677) clojure.math - fix method reflection in bodies and inlines, fix docstrings, renamed
+* [CLJ-2689](https://clojure.atlassian.net/browse/CLJ-2689) Fix clojure.math tests to be more tolerant of floating point comparisons
+
+### 3.2 Parser functions
+
+Added the following parsing functions to clojure.core:
+
+* `parse-double` - parses floating point number, including scientific notation
+* `parse-long` - parses integer in long range
+* `parse-boolean` - parses `"true"` or `"false"` to the canonical boolean values
+* `parse-uuid` - parses a UUID string to java.util.UUID
+
+All of these functions expect a string argument and return either the parsed value or `nil` if the value
+is in invalid format.
+
+* [CLJ-2667](https://clojure.atlassian.net/browse/CLJ-2667) Add functions to parse a single long/double/uuid/boolean from a string
+
+### 3.2 `random-uuid`
+
+Added `random-uuid`, a function to construct a random java.util.UUID.
+
+* [CLJ-1925](https://clojure.atlassian.net/browse/CLJ-1925) Add random-uuid
+
+### 3.3 `update-keys` and `update-vals`
+
+Added:
+
+* `update-keys` - applies a function to every key in a map, `m f => {(f k) v ...}`
+* `update-vals` - applies a function to every value in a map, `m f => {k (f v) ...}`
+
+* [CLJ-1959](https://clojure.atlassian.net/browse/CLJ-1959) Add implementation of update-keys
+* [CLJ-2651](https://clojure.atlassian.net/browse/CLJ-2651) Add implementation of update-vals
+
+### 3.4 `iteration`
+
+Added `iteration`, to repeatedly apply a (possibly impure) step function with continuation state.
+This can be used e.g. to consume APIs that return paginated or batched data.
+
+* [CLJ-2555](https://clojure.atlassian.net/browse/CLJ-2555) Add `iteration` generator function
+* [CLJ-2690](https://clojure.atlassian.net/browse/CLJ-2690) Improve `iteration` docstring and arg names
+* [CLJ-2685](https://clojure.atlassian.net/browse/CLJ-2685) Fix `iteration` generative test failure
+
+## 4 Fixes
+
+### 4.1 Compiler
+
+* [CLJ-2680](https://clojure.atlassian.net/browse/CLJ-2680) Fix type hinting a primitive local with matching type hint to not error
+* [CLJ-1180](https://clojure.atlassian.net/browse/CLJ-1180) Fix resolution of class type hints in `defprotocol`
+* [CLJ-1973](https://clojure.atlassian.net/browse/CLJ-1973) Make order of emitted protocol methods in generated classes reproducible
+
+### 4.2 Core
+
+* [CLJ-1879](https://clojure.atlassian.net/browse/CLJ-1879) IKVReduce - make IPersistentMap case faster and extend to Object, detaching it from any fully enumerable set of types
+* [CLJ-2065](https://clojure.atlassian.net/browse/CLJ-2065) IKVReduce - add direct support for SubVector
+* [CLJ-2663](https://clojure.atlassian.net/browse/CLJ-2663) Fix vector `=` not terminating when called with infinite sequence
+* [CLJ-2679](https://clojure.atlassian.net/browse/CLJ-2679) Fix hash collisions in `case` expressions on symbols
+* [CLJ-2600](https://clojure.atlassian.net/browse/CLJ-2600) Don't block `realized?` of `delay` on pending result
+* [CLJ-2649](https://clojure.atlassian.net/browse/CLJ-2649) Fix order of checks in `some-fn` and `every-pred` for 3 predicate case to match other unrollings
+* [CLJ-2234](https://clojure.atlassian.net/browse/CLJ-2234) Fix multimethod preferences to correctly use local hierarchy when it exists
+* [CLJ-2556](https://clojure.atlassian.net/browse/CLJ-2556) Fix `into` completion so `halt-when` works
+
+### 4.3 Performance
+
+* [CLJ-1808](https://clojure.atlassian.net/browse/CLJ-1808) `map-invert` should use `reduce-kv` and transient
+* [CLJ-2621](https://clojure.atlassian.net/browse/CLJ-2621) Fix unnecessary boxing of unused return in statement context for instance method expr
+* [CLJ-2670](https://clojure.atlassian.net/browse/CLJ-2670) Use Math.exact... methods for checked long math ops for performance
+* [CLJ-2636](https://clojure.atlassian.net/browse/CLJ-2636) Get rid of reflection on java.util.Properties when defining `*clojure-version*`
+* [CLJ-1509](https://clojure.atlassian.net/browse/CLJ-1509) AOT compile clojure.instant, clojure.uuid, clojure.core.reducers in build
+
+### 4.4 Error messages
+
+* [CLJ-2529](https://clojure.atlassian.net/browse/CLJ-2529) Fix incorrect reporting of runtime errors as compiler errors in calls through `Compiler.load()`
+* [CLJ-2350](https://clojure.atlassian.net/browse/CLJ-2350) Improve keyword arity exception message
+
+### 4.5 Docstrings
+
+* [CLJ-2249](https://clojure.atlassian.net/browse/CLJ-2249) Clarify `get` docstring regarding sets, strings, arrays, ILookup
+* [CLJ-2488](https://clojure.atlassian.net/browse/CLJ-2488) Add definition to `reify` docstring
+* [CLJ-1360](https://clojure.atlassian.net/browse/CLJ-1360) Update `clojure.string/split` docstring regarding trailing empty parts
+* [CLJ-2444](https://clojure.atlassian.net/browse/CLJ-2444) Fix typo in `test-vars` docstring
+* [CLJ-2666](https://clojure.atlassian.net/browse/CLJ-2666) Make Clojure Java API javadoc text match the example
+
+### 4.6 Other enhancements
+
+* [CLJ-2493](https://clojure.atlassian.net/browse/CLJ-2493) clojure.java.browse - Fix `browse-url` hanging on call to xdg-open
+* [CLJ-1908](https://clojure.atlassian.net/browse/CLJ-1908) clojure.test - Add `run-test` and `run-test-var` to run single test with fixtures and report
+* [CLJ-1379](https://clojure.atlassian.net/browse/CLJ-1379) clojure.test - Fix quoting of `:actual` form in `:pass` maps
+* [CLJ-2620](https://clojure.atlassian.net/browse/CLJ-2620) clojure.server - Fix asymmetric handling of `:exception` `:val`s in `prepl`
+* [CLJ-2387](https://clojure.atlassian.net/browse/CLJ-2387) clojure.server - Fix off-by-one in socket server port validation
+
+
 # Changes to Clojure in Version 1.10.3
 
 ## 1 Changes reverted

From 7b102d84c60ed88d62989d6fd4a6994bd33b3bec Mon Sep 17 00:00:00 2001
From: Paula Gearon 
Date: Sat, 5 Feb 2022 15:14:01 -0500
Subject: [PATCH 65/78] CLJ-2695: parse-double test does not test out-of range
 values

Signed-off-by: Alex Miller 
---
 test/clojure/test_clojure/parse.clj | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/test/clojure/test_clojure/parse.clj b/test/clojure/test_clojure/parse.clj
index 953beefb4d..8078c527f6 100644
--- a/test/clojure/test_clojure/parse.clj
+++ b/test/clojure/test_clojure/parse.clj
@@ -52,12 +52,15 @@
     "Infinity" Double/POSITIVE_INFINITY
     "-Infinity" Double/NEGATIVE_INFINITY
     "1.7976931348623157E308" Double/MAX_VALUE
-    "4.9E-324" Double/MIN_VALUE)
+    "4.9E-324" Double/MIN_VALUE
+    "1.7976931348623157E309" Double/POSITIVE_INFINITY  ;; past max double
+    "2.5e-324" Double/MIN_VALUE  ;; past min double, above half minimum
+    "2.4e-324" 0.0)  ;; below minimum double
   (is (Double/isNaN (parse-double "NaN")))
   (are [s] ;; nil on invalid string
-    (nil? (parse-long s))
-    "1.7976931348623157E309" ;; past max double
-    "9.9E-324")) ;; past min double
+    (nil? (parse-double s))
+    "double" ;; invalid string
+    "1.7976931348623157G309")) ;; invalid, but similar to valid
 
 ;; generative test - gen double -> str -> parse, compare
 (deftest test-gen-parse-double
@@ -96,4 +99,4 @@
     nil
     false
     true
-    100))
\ No newline at end of file
+    100))

From 0971ce23f4cb3a1042483c56a36e4954da26ca70 Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Wed, 16 Feb 2022 10:22:29 -0600
Subject: [PATCH 66/78] [maven-release-plugin] prepare release
 clojure-1.11.0-rc1

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 59159805a1..dc91d0a4aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-master-SNAPSHOT
+  1.11.0-rc1
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.0-rc1
   
 
   

From 9af0d1d9a0dc34c406c3588dfe9b60dbe4530981 Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Wed, 16 Feb 2022 10:22:29 -0600
Subject: [PATCH 67/78] [maven-release-plugin] prepare for next development
 iteration

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index dc91d0a4aa..59159805a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-rc1
+  1.11.0-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.0-rc1
+    HEAD
   
 
   

From f376cf62bb0c30f72b0df4ee94c38fa503fa4be7 Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Tue, 22 Mar 2022 10:16:08 -0500
Subject: [PATCH 68/78] [maven-release-plugin] prepare release clojure-1.11.0

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 59159805a1..e237f52448 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0-master-SNAPSHOT
+  1.11.0
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.0
   
 
   

From 48818bd96afc2c8ee8ee76075f7a186289c6517a Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Tue, 22 Mar 2022 10:16:08 -0500
Subject: [PATCH 69/78] [maven-release-plugin] prepare for next development
 iteration

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index e237f52448..2dd37faaad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.0
+  1.12.0-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.0
+    HEAD
   
 
   

From 1da6b07722790e898faa261a816a7a070fd93ac5 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Wed, 30 Mar 2022 15:41:32 -0500
Subject: [PATCH 70/78] CLJ-2701 Set serialVersionUIDs for Keyword and ArraySeq
 to retain 1.10.3 values

Signed-off-by: Alex Miller 
---
 src/jvm/clojure/lang/ArraySeq.java | 3 +++
 src/jvm/clojure/lang/Keyword.java  | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/src/jvm/clojure/lang/ArraySeq.java b/src/jvm/clojure/lang/ArraySeq.java
index 49a74b660d..5f54d87aaf 100644
--- a/src/jvm/clojure/lang/ArraySeq.java
+++ b/src/jvm/clojure/lang/ArraySeq.java
@@ -15,6 +15,9 @@
 import java.lang.reflect.Array;
 
 public class ArraySeq extends ASeq implements IndexedSeq, IReduce{
+
+private static final long serialVersionUID = -9069152683729302290L;
+
 public final Object[] array;
 final int i;
 //ISeq _rest;
diff --git a/src/jvm/clojure/lang/Keyword.java b/src/jvm/clojure/lang/Keyword.java
index 145df4f73b..253f455e4a 100644
--- a/src/jvm/clojure/lang/Keyword.java
+++ b/src/jvm/clojure/lang/Keyword.java
@@ -23,6 +23,8 @@
 
 public class Keyword implements IFn, Comparable, Named, Serializable, IHashEq {
 
+private static final long serialVersionUID = -2105088845257724163L;
+
 private static ConcurrentHashMap> table = new ConcurrentHashMap();
 static final ReferenceQueue rq = new ReferenceQueue();
 public final Symbol sym;

From e917dcc003bdd56660d5057407ea7739d2736af2 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Fri, 1 Apr 2022 12:46:31 -0500
Subject: [PATCH 71/78] Update changelog for 1.11.1

---
 changes.md | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/changes.md b/changes.md
index 46b45cbda1..f18b330f4a 100644
--- a/changes.md
+++ b/changes.md
@@ -1,5 +1,10 @@
 
 
+# Changes to Clojure in Version 1.11.1
+
+* [CLJ-2701](https://clojure.atlassian.net/browse/CLJ-2701)
+  Pin serialVersionUID for Keyword and ArraySeq back to 1.10.3 values to retain binary serialization
+
 # Changes to Clojure in Version 1.11.0
 
 ## 1 Compatibility

From 3f1c36d779a43b1951ddaa9cdf6250b1d739621b Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Fri, 1 Apr 2022 12:52:28 -0500
Subject: [PATCH 72/78] [maven-release-plugin] prepare release
 clojure-1.11.1-rc1

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2dd37faaad..4496e1353f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.12.0-master-SNAPSHOT
+  1.11.1-rc1
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.1-rc1
   
 
   

From cef38abac0d7139f4d38324290eaf2c40b8924a7 Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Fri, 1 Apr 2022 12:52:28 -0500
Subject: [PATCH 73/78] [maven-release-plugin] prepare for next development
 iteration

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4496e1353f..2dd37faaad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.1-rc1
+  1.12.0-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.1-rc1
+    HEAD
   
 
   

From ce55092f2b2f5481d25cff6205470c1335760ef6 Mon Sep 17 00:00:00 2001
From: Clojure Build 
Date: Tue, 5 Apr 2022 09:33:41 -0500
Subject: [PATCH 74/78] [maven-release-plugin] prepare release clojure-1.11.1

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2dd37faaad..b15f640224 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.12.0-master-SNAPSHOT
+  1.11.1
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    HEAD
+    clojure-1.11.1
   
 
   

From 777456f5f485ed42cee386344fbce891c559ec4e Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Thu, 7 Mar 2024 12:54:43 -0600
Subject: [PATCH 75/78] CLJ-2839 Infinite seq class hashCode() is infinite loop

---
 src/clj/clojure/core.clj                    |  3 ++-
 src/jvm/clojure/lang/Cycle.java             |  9 +++++++++
 src/jvm/clojure/lang/Iterate.java           |  8 ++++++++
 src/jvm/clojure/lang/Repeat.java            | 13 +++++++++++++
 test/clojure/test_clojure/sequences.clj     | 10 ++++++++++
 test/clojure/test_clojure/serialization.clj |  9 ++++++++-
 6 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 42abb7f00a..1e7c6977cc 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -3028,7 +3028,8 @@
   [n x] (take n (repeat x)))
 
 (defn iterate
-  "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"
+  "Returns a lazy (infinite!) sequence of x, (f x), (f (f x)) etc.
+  f must be free of side-effects"
   {:added "1.0"
    :static true}
   [f x] (clojure.lang.Iterate/create f x) )
diff --git a/src/jvm/clojure/lang/Cycle.java b/src/jvm/clojure/lang/Cycle.java
index 877695558a..0be07b5949 100644
--- a/src/jvm/clojure/lang/Cycle.java
+++ b/src/jvm/clojure/lang/Cycle.java
@@ -93,4 +93,13 @@ public Object reduce(IFn f, Object start){
             s = all;
     }
 }
+
+public int hashCode(){
+    throw new UnsupportedOperationException();
+}
+
+public int hasheq(){
+    throw new UnsupportedOperationException();
+}
+
 }
diff --git a/src/jvm/clojure/lang/Iterate.java b/src/jvm/clojure/lang/Iterate.java
index aec0c14aa2..5aaf9cbb52 100644
--- a/src/jvm/clojure/lang/Iterate.java
+++ b/src/jvm/clojure/lang/Iterate.java
@@ -84,4 +84,12 @@ public Object reduce(IFn rf, Object start){
         v = f.invoke(v);
     }
 }
+
+public int hashCode(){
+    throw new UnsupportedOperationException();
+}
+
+public int hasheq(){
+    throw new UnsupportedOperationException();
+}
 }
diff --git a/src/jvm/clojure/lang/Repeat.java b/src/jvm/clojure/lang/Repeat.java
index 2ce4f2dab2..9547d66523 100644
--- a/src/jvm/clojure/lang/Repeat.java
+++ b/src/jvm/clojure/lang/Repeat.java
@@ -97,4 +97,17 @@ public Object reduce(IFn f, Object start){
     }
 }
 
+public int hashCode(){
+    if(count <= 0)
+        throw new UnsupportedOperationException();
+    else
+        return super.hashCode();
+}
+
+public int hasheq(){
+    if(count <= 0)
+        throw new UnsupportedOperationException();
+    else
+        return super.hasheq();
+}
 }
diff --git a/test/clojure/test_clojure/sequences.clj b/test/clojure/test_clojure/sequences.clj
index 4eb99e7860..f0927061a4 100644
--- a/test/clojure/test_clojure/sequences.clj
+++ b/test/clojure/test_clojure/sequences.clj
@@ -1458,6 +1458,16 @@
                            :kf #(some-> % :k #{0 1 2})
                            :vf :item))))))
 
+(deftest infinite-seq-hash
+  (are [e] (thrown? Exception (.hashCode ^Object e))
+    (iterate identity nil)
+    (cycle [1])
+    (repeat 1))
+  (are [e] (thrown? Exception (.hasheq ^clojure.lang.IHashEq e))
+    (iterate identity nil)
+    (cycle [1])
+    (repeat 1)))
+
 (defspec iteration-seq-equals-reduce 1000
   (prop/for-all [initk gen/int
                  seed gen/int]
diff --git a/test/clojure/test_clojure/serialization.clj b/test/clojure/test_clojure/serialization.clj
index 51a0d6a263..c9befc49cd 100644
--- a/test/clojure/test_clojure/serialization.clj
+++ b/test/clojure/test_clojure/serialization.clj
@@ -183,4 +183,11 @@
 
     ;; stateful seqs
     (enumeration-seq (java.util.Collections/enumeration (range 50)))
-    (iterator-seq (.iterator (range 50)))))
\ No newline at end of file
+    (iterator-seq (.iterator (range 50)))))
+
+;; necessary for CVE-2024-22871
+(deftest CLJ-2839
+  (are [e] (thrown? Exception (.hashCode ^Object (-> e serialize deserialize)))
+    (repeat 1)
+    (iterate identity nil)
+    (cycle [1])))
\ No newline at end of file

From 5366a0e9e6df8ade159772703da3ac32c352fcdc Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Fri, 8 Mar 2024 08:41:03 -0600
Subject: [PATCH 76/78] add github actions to clojure-1.11-dev branch

---
 .github/workflows/release.yml  | 19 +++++++++++++++++++
 .github/workflows/snapshot.yml |  8 ++++++++
 .github/workflows/test.yml     | 26 ++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 .github/workflows/release.yml
 create mode 100644 .github/workflows/snapshot.yml
 create mode 100644 .github/workflows/test.yml

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000000..d30437293c
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,19 @@
+name: Release on demand
+
+on:
+  workflow_dispatch:
+    inputs:
+      releaseVersion:
+        description: "Version to release"
+        required: true
+      snapshotVersion:
+        description: "Snapshot version after release"
+        required: true
+
+jobs:
+  call-release:
+    uses: clojure/build.ci/.github/workflows/release.yml@master
+    with:
+      releaseVersion: ${{ github.event.inputs.releaseVersion }}
+      snapshotVersion: ${{ github.event.inputs.snapshotVersion }}
+    secrets: inherit
diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
new file mode 100644
index 0000000000..24729578c1
--- /dev/null
+++ b/.github/workflows/snapshot.yml
@@ -0,0 +1,8 @@
+name: Snapshot on demand
+
+on: [workflow_dispatch]
+
+jobs:
+  call-snapshot:
+    uses: clojure/build.ci/.github/workflows/snapshot.yml@master
+    secrets: inherit
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000000..b50a9813d1
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,26 @@
+name: Test
+
+on:
+  push:
+  workflow_dispatch:
+
+jobs:
+  test:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest] # macOS-latest, windows-latest]
+        java-version: ["8", "11", "17", "21"]
+        distribution: ["temurin", "corretto"]
+        profile: ["test-direct", "test-no-direct"]
+    runs-on: ${{ matrix.os }}
+    steps:
+    - uses: actions/checkout@v3
+    - name: Set up Java
+      uses: actions/setup-java@v3
+      with:
+        java-version: ${{ matrix.java-version }}
+        distribution: ${{ matrix.distribution }}
+        cache: 'maven'
+    - name: Build with Maven
+      run: mvn -ntp -B -P${{ matrix.profile }} clean test

From 63474dbaf356cbbc38ed9bd9f3a01c5800b8a6c4 Mon Sep 17 00:00:00 2001
From: Alex Miller 
Date: Fri, 8 Mar 2024 08:44:11 -0600
Subject: [PATCH 77/78] update pom to snapshot version

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index b15f640224..24ea0e131f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.1
+  1.11.2-master-SNAPSHOT
 
   http://clojure.org/
   Clojure core environment and runtime library.

From 218054f1f2ddfc69ef4f9d17f916de35e4a4effe Mon Sep 17 00:00:00 2001
From: clojure-build 
Date: Fri, 8 Mar 2024 14:46:47 +0000
Subject: [PATCH 78/78] [maven-release-plugin] prepare release clojure-1.11.2

---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 24ea0e131f..a36970cfce 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
   clojure
   clojure
   jar
-  1.11.2-master-SNAPSHOT
+  1.11.2
 
   http://clojure.org/
   Clojure core environment and runtime library.
@@ -30,7 +30,7 @@
     scm:git:git@github.com:clojure/clojure.git
     scm:git:git@github.com:clojure/clojure.git
     git@github.com:clojure/clojure.git
-    clojure-1.11.1
+    clojure-1.11.2