Specialize record field reads in method bodies; fix with-meta on symbols (#141)
A protocol method reads its fields through the generic guarded keyword lookup because the method's `this` param is untyped. defrecord now hints `this` with the record type, the per-form inference seeds ^Record-hinted params (the :fn branch previously typed all params :any — only the whole-program path seeded phints), and run-passes feeds the inference the record shapes. So a hinted param's field reads bare-index instead of going through the :jolt/type tag guard. This needed a with-meta fix: (with-meta sym ..) returned a proto'd table, so symbol? was false and the macro-attached hint broke fn destructuring. Symbols now carry metadata in-place in their struct (matching how the reader attaches ^hint), keeping symbol? true, as in Clojure. Modest on dispatch (~3-5%): the field read is a small fraction of a dispatch; the machinery (record-tag + protocol lookup + wrapper) dominates, which is the inline-cache target (jolt-ez5h). But it's a correctness fix and lets any ^Record-hinted code — not just methods — drop the field-read guard per-form, not only under whole-program. Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
7d0b1d5695
commit
6772e28eae
4 changed files with 32 additions and 6 deletions
|
|
@ -55,9 +55,17 @@
|
|||
(defn core-with-meta [obj meta]
|
||||
# Functions and scalars can't carry metadata in Jolt's model — return as-is
|
||||
# rather than crashing (Clojure attaches meta only to IObj values).
|
||||
(if (or (function? obj) (cfunction? obj) (number? obj) (boolean? obj)
|
||||
(nil? obj) (string? obj) (keyword? obj) (buffer? obj))
|
||||
(cond
|
||||
(or (function? obj) (cfunction? obj) (number? obj) (boolean? obj)
|
||||
(nil? obj) (string? obj) (keyword? obj) (buffer? obj))
|
||||
obj
|
||||
# Symbols carry metadata IN-PLACE in their struct's :meta field (this is how
|
||||
# the reader attaches ^hint and keeps symbol? true — see reader/read-meta).
|
||||
# The table-proto path below would make (symbol? (with-meta sym ..)) false and
|
||||
# break destructuring/hint reading, so keep a symbol a symbol.
|
||||
(and (struct? obj) (= :symbol (obj :jolt/type)))
|
||||
(struct ;(kvs obj) :meta meta)
|
||||
true
|
||||
(do
|
||||
(var new-obj @{})
|
||||
(each k (keys obj)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue