#7139 recovered rule-5 eligibility for 84 of 85 CommonJS dependency modules and
recorded that of the ~103 Ptr<Shape> candidates it freed, 100 were
immediately re-denied by rule 2 — reading as "containment is the wall in
dependency JS". Track D (#7034 §3, PR #7149) was scheduled on that basis.
Measured, it is not containment. Two compiler arms — #7139 alone, and
#7139 + #7149 — over 180 real __esModule CJS modules from
real-apps/scriptc/node_modules (perry compile m.js --opt-report --no-link,
180/180 compiled in both, every count identical between arms):
| bucket |
candidates |
| rule 1 — allocated in expression position, never bound to a local |
506 |
| rule 5 — module barrier still armed |
99 |
| rule 2 — bare reference |
130 |
| rule 2 — call argument |
5 |
| rule 2 — array element |
1 |
| rule 2 — closure capture |
1 |
| rule 2 — undeclared property |
1 |
| total candidates |
746 |
| selected / consumed |
3 / 0 |
Two things fall out.
1. Rule 1 is the wall, and its shape is known
The 506 unbound allocations break down by position:
| position |
count |
| constructor argument |
182 |
| statement |
162 |
| call argument |
84 |
| return |
64 |
| array element |
8 |
| initializer |
6 |
new X(…) written directly into an argument, a statement, or a return, never
bound to a let/const. Rule 1 needs a local to anchor the proof to, and
transpiled/minified code does not create one. This is the .map(x => ({…})) /
return {…} idiom the report already names — at 68% of all candidates it is
larger than every containment position combined by a factor of ~3.5.
2. The rule-2 "bare reference" denials are Perry's own scaffolding
All 130 are the local __cjs_module. That is the CommonJS wrapper's own
binding, not user code — the same family #7139 was narrowing. Whether it is
worth exempting depends on whether __cjs_module's object is ever a useful
Ptr<Shape> candidate at all; if it is not, it should not be a candidate,
and the 130 denials are noise in every report.
Caveat on the corpus
This is not #7139's exact 85-module set (that selection was
"self-contained __esModule leaves"; this one is every third __esModule file
by sorted path, requires allowed). A tighter 82-module self-contained set gave
the same shape: 185 candidates, 100 rule 1, 82 rule 2 — all 82 __cjs_module
bare references, 0 element. The conclusion does not depend on the sample.
What this changes
Nothing about #7149 — it pays on app-shaped TypeScript, where it removes every
guard diamond from a build-then-consume loop. But call argument (#7034 §1)
should not be scheduled on the assumption that it unlocks dependency JS
either: it is 5 of 746. The dependency-JS lever is rule 1, and its fix is a
different mechanism — anchoring the proof to an allocation site rather than to
a binding.
#7139 recovered rule-5 eligibility for 84 of 85 CommonJS dependency modules and
recorded that of the ~103
Ptr<Shape>candidates it freed, 100 wereimmediately re-denied by rule 2 — reading as "containment is the wall in
dependency JS". Track D (#7034 §3, PR #7149) was scheduled on that basis.
Measured, it is not containment. Two compiler arms — #7139 alone, and
#7139 + #7149 — over 180 real
__esModuleCJS modules fromreal-apps/scriptc/node_modules(perry compile m.js --opt-report --no-link,180/180 compiled in both, every count identical between arms):
Two things fall out.
1. Rule 1 is the wall, and its shape is known
The 506 unbound allocations break down by position:
new X(…)written directly into an argument, a statement, or a return, neverbound to a
let/const. Rule 1 needs a local to anchor the proof to, andtranspiled/minified code does not create one. This is the
.map(x => ({…}))/return {…}idiom the report already names — at 68% of all candidates it islarger than every containment position combined by a factor of ~3.5.
2. The rule-2 "bare reference" denials are Perry's own scaffolding
All 130 are the local
__cjs_module. That is the CommonJS wrapper's ownbinding, not user code — the same family #7139 was narrowing. Whether it is
worth exempting depends on whether
__cjs_module's object is ever a usefulPtr<Shape>candidate at all; if it is not, it should not be a candidate,and the 130 denials are noise in every report.
Caveat on the corpus
This is not #7139's exact 85-module set (that selection was
"self-contained
__esModuleleaves"; this one is every third__esModulefileby sorted path, requires allowed). A tighter 82-module self-contained set gave
the same shape: 185 candidates, 100 rule 1, 82 rule 2 — all 82
__cjs_modulebare references, 0 element. The conclusion does not depend on the sample.
What this changes
Nothing about #7149 — it pays on app-shaped TypeScript, where it removes every
guard diamond from a build-then-consume loop. But
call argument(#7034 §1)should not be scheduled on the assumption that it unlocks dependency JS
either: it is 5 of 746. The dependency-JS lever is rule 1, and its fix is a
different mechanism — anchoring the proof to an allocation site rather than to
a binding.