Fix [_ _] inline method field binding + Var protocol dispatch
Two gaps reitit-core surfaced (now 322/0/1 -> 327/0/0): - A deftype/defrecord inline method with two _ params, (m [_ _] field), read the field as nil: mk-clause bound fields off (get _ :field) where _ was the first param, but the second _ shadowed it. Each _ param is now renamed to a fresh symbol so the instance is unambiguous. - A var did not dispatch to a protocol's clojure.lang.Var extension (reitit extends Expand to Var for a #'handler route): value-host-tags gained a var arm (Var/clojure.lang.Var/IDeref/IFn) and host-type-set gained Var/IDeref so the extension keys under Var. deftype/defrecord is a seed source, re-minted.
This commit is contained in:
parent
9404512b97
commit
6b99591266
5 changed files with 633 additions and 621 deletions
|
|
@ -377,7 +377,9 @@
|
|||
;; The clause is DATA, not a syntax-quote: a body that is itself a syntax-
|
||||
;; quote would have its ~unquotes consumed a level early if re-spliced.
|
||||
mk-clause (fn [spec]
|
||||
(let [argv (nth spec 1)
|
||||
;; fresh-name each _ param so two _ params don't collide on the
|
||||
;; field binds / live-read instance (see defrecord's mk-clause).
|
||||
(let [argv (mapv (fn [p] (if (= p (quote _)) (gensym "_p") p)) (nth spec 1))
|
||||
inst (first argv)
|
||||
;; let-bind only immutable fields; mutable ones are read live
|
||||
;; via rewrite-body so a set! within the method is observed.
|
||||
|
|
@ -597,7 +599,11 @@
|
|||
;; one clause from a spec; `this` is hinted with the record type so the
|
||||
;; inference reads its fields bare-index. Clause as DATA (see deftype).
|
||||
mk-clause (fn [spec]
|
||||
(let [argv (nth spec 1)
|
||||
;; rename each _ parameter to a fresh symbol so two _ params
|
||||
;; (the common (m [_ _] …) on a 1-arg protocol method) don't
|
||||
;; collide — the field binds read (get this :field) off the
|
||||
;; FIRST param, which an ignored second _ would otherwise shadow.
|
||||
(let [argv (mapv (fn [p] (if (= p (quote _)) (gensym "_p") p)) (nth spec 1))
|
||||
inst (first argv)
|
||||
hinted (assoc argv 0 (vary-meta inst assoc :tag (name name-sym)))
|
||||
binds (vec (mapcat (fn [f] [f `(get ~inst ~(keyword (name f)))]) fields))]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue