Commit c740f88
fix(runtime): a generic specialization answers with its generic's constructor and prototype entries (#7826)
* fix(runtime): a generic specialization answers with its generic's constructor and prototype entries
`new Gen<number>()` is monomorphized into a separate class (`Gen$num`,
`monomorph::mangle::generate_specialized_name`) with its own class id, and the
instance is stamped with THAT id. TypeScript erases type arguments, so at
runtime there is exactly one `Gen` — the specializations are an implementation
detail that was leaking through the id-keyed surfaces.
#7575 fixed `instanceof`, #7632 fixed `constructor.name`, #7762 fixed the two
prototype-object registries. Two holes remained, both keyed on the raw id:
1. THE CONSTRUCTOR VALUE. `class_object_props`'s instance arm synthesized the
class ref straight from `(*obj).class_id`, so `a.constructor !== Gen` and
`a.constructor !== b.constructor`. #7632 made this WORSE before better: both
report the name `Gen`, so two values printed identically and compared
unequal.
2. THE PROPERTY LOOKUP CHAIN — the one #7762's prototype-object aliasing did
not reach, and the more damaging of the pair. `lookup_prototype_method`
walked the PARENT chain from the specialization's id, so a patch on
`Gen.prototype` was invisible on a specialized instance:
`Gen.prototype.tag = "G"` then `a.tag` gave `undefined` while
`Object.getPrototypeOf(a) === Gen.prototype` reported `true`. The two edges
disagreed about the same object.
Both take the origin edge the other three surfaces already take. In the chain
walk the generic is tried BEFORE the parent, because it is an alias rather than
an ancestor — a specialization's parent chain is its generic's parent chain, so
hopping to the parent first would walk past `Gen` and never come back. That
also keeps the walk line-count-neutral, which `construct.rs` requires: it sits
exactly at the 2000-line cap.
METHOD DISPATCH IS DELIBERATELY NOT ALIASED. It runs off the per-class-id
vtable, so each specialization keeps its own monomorphized bodies — the same
boundary #7762 drew, and the reason this is not a `CLASS_REGISTRY` parent edge
(that chain also resolves `super()` construction and would re-run the wrong
constructor).
`test-files/test_gap_generic_specialization_constructor_identity_7757.ts` is
byte-identical to node. It pins the edge in the negative direction too: two
different generics stay distinct, a specialized SUBCLASS reports the subclass
rather than the base, and declared methods still dispatch per specialization.
Fixes #7757
* docs(changelog): add fragment for the #7757 specialization identity fix
---------
Co-authored-by: Ralph Küpper <ralph@skelpo.com>1 parent 3eea8c7 commit c740f88
4 files changed
Lines changed: 120 additions & 2 deletions
File tree
- changelog.d
- crates/perry-runtime/src/object
- class_registry
- field_get_set
- test-files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1934 | 1934 | | |
1935 | 1935 | | |
1936 | 1936 | | |
1937 | | - | |
| 1937 | + | |
1938 | 1938 | | |
1939 | 1939 | | |
1940 | 1940 | | |
| |||
Lines changed: 16 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
54 | 54 | | |
55 | 55 | | |
56 | 56 | | |
57 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
58 | 73 | | |
59 | 74 | | |
60 | 75 | | |
| |||
Lines changed: 82 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
0 commit comments