   [opts]
   (reduce into #{} [(:stub opts) (keys (:replace opts)) (keys (:spec opts))]))
 
-(defn- sym-matcher
-  "Returns a fn that matches symbols that are either in syms,
-or whose namespace is in syms."
-  [syms]
-  (let [names (into #{} (map str) syms)]
-    (fn [s]
-      (or (contains? names (namespace s))
-          (contains? names (str s))))))
-
-(defn- validate-opts
-  [opts]
-  (assert (every? ident? (keys (:gen opts))) "instrument :gen expects ident keys"))
+(defn- fn-spec-name?
+  [s]
+  (symbol? s))
+
+(defn instrumentable-syms
+  "Given an opts map as per instrument, returns the set of syms
+that can be instrumented."
+  ([] (instrumentable-syms nil))
+  ([opts]
+     (assert (every? ident? (keys (:gen opts))) "instrument :gen expects ident keys")
+     (reduce into #{} [(filter fn-spec-name? (keys (s/registry)))
+                       (keys (:spec opts))
+                       (:stub opts)
+                       (keys (:replace opts))])))
 
 (defn instrument
-  "Instruments the vars matched by ns-or-names, a symbol or a
-collection of symbols. Instruments the current namespace if
-ns-or-names not specified. Idempotent.
-
-A var matches ns-or-names if ns-or-names includes either the var's
-fully qualified name or the var's namespace.
+  "Instruments the vars named by sym-or-syms, a symbol or collection
+of symbols, or all instrumentable vars if sym-or-syms is not
+specified.
 
 If a var has an :args fn-spec, sets the var's root binding to a
 fn that checks arg conformance (throwing an exception on failure)
 before delegating to the original fn.
 
 The opts map can be used to override registered specs, and/or to
-replace fn implementations entirely. Opts for symbols not matched
-by ns-or-names are ignored. This facilitates sharing a common
+replace fn implementations entirely. Opts for symbols not included
+in sym-or-syms are ignored. This facilitates sharing a common
 options map across many different calls to instrument.
 
 The opts map may have the following keys:
 
   :spec     a map from var-name symbols to override specs
-  :stub     a collection of var-name symbols to be replaced by stubs
+  :stub     a set of var-name symbols to be replaced by stubs
   :gen      a map from spec names to generator overrides
   :replace  a map from var-name symbols to replacement fns
 

              (explain-test args (:fn specs) {:args cargs :ret cret} :fn))
            true))))))

(defn- throwable?
  [x]
  (instance? Throwable x))

(defn- check-fn
  [f specs {gen :gen opts ::stc/opts}]
  (let [{:keys [num-tests] :or {num-tests 100}} opts

(in-ns 'clojure.spec.test)
(alias 'stc 'clojure.spec.test.check)

(defn- throwable?
  [x]
  (instance? Throwable x))

(defn ->sym
  [x]
  (@#'s/->sym x))

(defn- ->var
  [s-or-v]
  (if (var? s-or-v)
    s-or-v
    (let [v (and (symbol? s-or-v) (resolve s-or-v))]
      (if (var? v)
        v
        (throw (IllegalArgumentException. (str (pr-str s-or-v) " does not name a var")))))))

(defn- collectionize
  [x]
  (if (symbol? x)
    (list x)
    x))

(defn enumerate-namespace
  "Given a symbol naming an ns, or a collection of such symbols,
returns the set of all symbols naming vars in those nses."
  [ns-sym-or-syms]
  (into
   #{}
   (mapcat (fn [ns-sym]
             (map
              (fn [name-sym]
                (symbol (name ns-sym) (name name-sym)))
              (keys (ns-interns ns-sym)))))
   (collectionize ns-sym-or-syms)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; instrument ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(def ^:private ^:dynamic *instrument-enabled*
  "if false, instrumented fns call straight through"
  true)
