diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc index 88871a08c..e414923f1 100644 --- a/src/main/clojure/cljs/analyzer.cljc +++ b/src/main/clojure/cljs/analyzer.cljc @@ -2510,13 +2510,14 @@ x (not (contains? ret :info))) (loop [bes [] env (assoc encl-env :context :expr) bindings (seq (partition 2 bindings))] - (if-some [[name init] (first bindings)] - (let [] + (do (when (or (some? (namespace name)) #?(:clj (.contains (str name) ".") :cljs ^boolean (goog.string/contains (str name) "."))) (throw (error encl-env (str "Invalid local name: " name)))) + (when (= '& name) + (throw (error encl-env "Can't use & as a local binding"))) (let [init-expr (analyze-let-binding-init env init (cons {:params bes} *loop-lets*)) line (get-line name env) col (get-col name env) diff --git a/src/test/clojure/cljs/compiler_tests.clj b/src/test/clojure/cljs/compiler_tests.clj index f6f7b560b..8b47e0fb8 100644 --- a/src/test/clojure/cljs/compiler_tests.clj +++ b/src/test/clojure/cljs/compiler_tests.clj @@ -401,6 +401,30 @@ (if (gobject/containsKey nil nil) true false)]))] (is (nil? (re-find #"truth_" code)))))) +(deftest test-amp-as-local-clj-2954 + (testing "& disallowed as local binding" + (try + (env/with-compiler-env (env/default-compiler-env) + (compile-form-seq + '[(let [& 42] &)])) + (catch Throwable t + (is (instance? clojure.lang.ExceptionInfo t)) + (is (.startsWith (-> t ex-cause ex-message) "Can't use & as a local binding")))) + (try + (env/with-compiler-env (env/default-compiler-env) + (compile-form-seq + '[(let* [& 42] &)])) + (catch Throwable t + (is (instance? clojure.lang.ExceptionInfo t)) + (is (.startsWith (-> t ex-cause ex-message) "Can't use & as a local binding")))) + (try + (env/with-compiler-env (env/default-compiler-env) + (compile-form-seq + '[(loop* [& 42] &)])) + (catch Throwable t + (is (instance? clojure.lang.ExceptionInfo t)) + (is (.startsWith (-> t ex-cause ex-message) "Can't use & as a local binding")))))) + ;; CLJS-1225 (comment