diff options
-rw-r--r-- | src/clj/clojure/main.clj | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Namespace.java | 14 | ||||
-rw-r--r-- | test/clojure/test_clojure/rt.clj | 31 |
3 files changed, 39 insertions, 8 deletions
diff --git a/src/clj/clojure/main.clj b/src/clj/clojure/main.clj index e607440c..19aea435 100644 --- a/src/clj/clojure/main.clj +++ b/src/clj/clojure/main.clj @@ -194,7 +194,7 @@ (catch Throwable e (caught e) (set! *e e))) - (use 'clojure.repl) + (use '[clojure.repl :only (source-fn source apropos dir-fn dir)]) (prompt) (flush) (loop [] diff --git a/src/jvm/clojure/lang/Namespace.java b/src/jvm/clojure/lang/Namespace.java index 383719f5..4c557a9a 100644 --- a/src/jvm/clojure/lang/Namespace.java +++ b/src/jvm/clojure/lang/Namespace.java @@ -66,12 +66,10 @@ public Var intern(Symbol sym){ if(o instanceof Var && ((Var) o).ns == this) return (Var) o; -// throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); - if(v == null) v = new Var(this, sym); - warnOnReplace(sym, o, v); + warnOrFailOnReplace(sym, o, v); while(!mappings.compareAndSet(map, map.assoc(sym, v))) @@ -80,7 +78,12 @@ public Var intern(Symbol sym){ return v; } -private void warnOnReplace(Symbol sym, Object o, Object v){ +private void warnOrFailOnReplace(Symbol sym, Object o, Object v){ + if (o instanceof Var) { + if (((Var)o).ns != RT.CLOJURE_NS) { + throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); + } + } RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + o + " in namespace: " + name + ", being replaced by: " + v); } @@ -101,8 +104,7 @@ Object reference(Symbol sym, Object val){ if(o == val) return o; -// throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); - warnOnReplace(sym, o, val); + warnOrFailOnReplace(sym, o, val); while(!mappings.compareAndSet(map, map.assoc(sym, val))) map = getMappings(); diff --git a/test/clojure/test_clojure/rt.clj b/test/clojure/test_clojure/rt.clj index 3a63c029..e72d4e06 100644 --- a/test/clojure/test_clojure/rt.clj +++ b/test/clojure/test_clojure/rt.clj @@ -30,6 +30,14 @@ ~@body (str s#)))) +(defn temp-ns + "Create and return a temporary ns, using clojure.core + uses" + [& uses] + (binding [*ns* *ns*] + (in-ns (gensym)) + (apply clojure.core/use 'clojure.core uses) + *ns*)) + (defmacro eval-in-temp-ns [form] `(binding [*ns* *ns*] (in-ns (gensym)) @@ -45,7 +53,7 @@ (is (re-matches msg-re (with-err-print-writer (eval-in-temp-ns form)))))) (deftest error-messages - (testing "binding a var that already refers to something" + (testing "binding a core var that already refers to something" (should-print-err-message #"WARNING: prefers already refers to: #'clojure.core/prefers in namespace: .*\n" (defn prefers [] (throw (RuntimeException. "rebound!"))))) @@ -72,3 +80,24 @@ (is (contains? (meta #'example-var) :macro)) (.bindRoot #'example-var 0) (is (not (contains? (meta #'example-var) :macro)))) + +(deftest last-var-wins-for-core + (testing "you can replace a core name, with warning" + (let [ns (temp-ns 'clojure.set) + replacement (gensym)] + (with-err-string-writer (intern ns 'prefers replacement)) + (is (= replacement @('prefers (ns-publics ns)))))) + (testing "you cannot intern over an existing non-core name" + (let [ns (temp-ns 'clojure.set) + replacement (gensym)] + (is (thrown? IllegalStateException + (intern ns 'subset? replacement))) + (is (nil? ('subset? (ns-publics ns)))) + (is (= #'clojure.set/subset? ('subset? (ns-refers ns)))))) + (testing "you cannot refer over an existing non-core name" + (let [ns (temp-ns 'clojure.set) + replacement (gensym)] + (is (thrown? IllegalStateException + (.refer ns 'subset? #'clojure.set/intersection))) + (is (nil? ('subset? (ns-publics ns)))) + (is (= #'clojure.set/subset? ('subset? (ns-refers ns))))))) |