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:
Yogthos 2026-06-26 23:22:22 -04:00
parent 9404512b97
commit 6b99591266
5 changed files with 633 additions and 621 deletions

View file

@ -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))]