@scriptc/compiler 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (588) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +7 -18
  2. package/dist/backend/cycle-analysis.d.ts +21 -9
  3. package/dist/backend/cycle-analysis.js +139 -67
  4. package/dist/backend/cycle-analysis.js.map +1 -1
  5. package/dist/backend/cycle-analysis.test.js +283 -3
  6. package/dist/backend/cycle-analysis.test.js.map +1 -1
  7. package/dist/backend/cycle-mutability.d.ts +39 -0
  8. package/dist/backend/cycle-mutability.js +205 -0
  9. package/dist/backend/cycle-mutability.js.map +1 -0
  10. package/dist/backend/link-plan-core.d.ts +2 -1
  11. package/dist/backend/link-plan-core.js +15 -3
  12. package/dist/backend/link-plan-core.js.map +1 -1
  13. package/dist/backend/link-plan.d.ts +2 -1
  14. package/dist/backend/link-plan.js.map +1 -1
  15. package/dist/backend/llvm/alloc.d.ts +43 -0
  16. package/dist/backend/llvm/alloc.js +246 -0
  17. package/dist/backend/llvm/alloc.js.map +1 -0
  18. package/dist/backend/llvm/alloc.test.d.ts +1 -0
  19. package/dist/backend/llvm/alloc.test.js +102 -0
  20. package/dist/backend/llvm/alloc.test.js.map +1 -0
  21. package/dist/backend/llvm/blocks.d.ts +9 -0
  22. package/dist/backend/llvm/blocks.js +9 -0
  23. package/dist/backend/llvm/blocks.js.map +1 -1
  24. package/dist/backend/llvm/borrowed-receivers.d.ts +7 -0
  25. package/dist/backend/llvm/borrowed-receivers.js +39 -0
  26. package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
  27. package/dist/backend/llvm/call-lifetimes.d.ts +18 -3
  28. package/dist/backend/llvm/call-lifetimes.js +54 -19
  29. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  30. package/dist/backend/llvm/call-lifetimes.test.js +178 -3
  31. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  32. package/dist/backend/llvm/checked-narrows.d.ts +24 -0
  33. package/dist/backend/llvm/checked-narrows.js +108 -0
  34. package/dist/backend/llvm/checked-narrows.js.map +1 -0
  35. package/dist/backend/llvm/checked-narrows.test.d.ts +1 -0
  36. package/dist/backend/llvm/checked-narrows.test.js +208 -0
  37. package/dist/backend/llvm/checked-narrows.test.js.map +1 -0
  38. package/dist/backend/llvm/classes.d.ts +16 -1
  39. package/dist/backend/llvm/classes.js +60 -49
  40. package/dist/backend/llvm/classes.js.map +1 -1
  41. package/dist/backend/llvm/classes.test.js +68 -6
  42. package/dist/backend/llvm/classes.test.js.map +1 -1
  43. package/dist/backend/llvm/common.d.ts +13 -0
  44. package/dist/backend/llvm/common.js +30 -0
  45. package/dist/backend/llvm/common.js.map +1 -1
  46. package/dist/backend/llvm/constant-callbacks.d.ts +19 -3
  47. package/dist/backend/llvm/constant-callbacks.js +289 -52
  48. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  49. package/dist/backend/llvm/constant-callbacks.test.js +140 -3
  50. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
  51. package/dist/backend/llvm/debug-info.d.ts +6 -2
  52. package/dist/backend/llvm/debug-info.js +11 -1
  53. package/dist/backend/llvm/debug-info.js.map +1 -1
  54. package/dist/backend/llvm/dense-array-access.d.ts +29 -0
  55. package/dist/backend/llvm/dense-array-access.js +335 -0
  56. package/dist/backend/llvm/dense-array-access.js.map +1 -0
  57. package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
  58. package/dist/backend/llvm/dense-array-access.test.js +238 -0
  59. package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
  60. package/dist/backend/llvm/dyn.d.ts +38 -0
  61. package/dist/backend/llvm/dyn.js +213 -14
  62. package/dist/backend/llvm/dyn.js.map +1 -1
  63. package/dist/backend/llvm/emitter.d.ts +308 -15
  64. package/dist/backend/llvm/emitter.js +1788 -206
  65. package/dist/backend/llvm/emitter.js.map +1 -1
  66. package/dist/backend/llvm/emitter.test.js +89 -7
  67. package/dist/backend/llvm/emitter.test.js.map +1 -1
  68. package/dist/backend/llvm/expr-async.js +62 -8
  69. package/dist/backend/llvm/expr-async.js.map +1 -1
  70. package/dist/backend/llvm/expr-async.test.d.ts +1 -0
  71. package/dist/backend/llvm/expr-async.test.js +62 -0
  72. package/dist/backend/llvm/expr-async.test.js.map +1 -0
  73. package/dist/backend/llvm/expr-bytes.d.ts +1 -1
  74. package/dist/backend/llvm/expr-bytes.js +85 -8
  75. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  76. package/dist/backend/llvm/expr-callbacks.js +29 -21
  77. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  78. package/dist/backend/llvm/expr-calls.d.ts +5 -0
  79. package/dist/backend/llvm/expr-calls.js +118 -15
  80. package/dist/backend/llvm/expr-calls.js.map +1 -1
  81. package/dist/backend/llvm/expr-containers.d.ts +7 -1
  82. package/dist/backend/llvm/expr-containers.js +246 -32
  83. package/dist/backend/llvm/expr-containers.js.map +1 -1
  84. package/dist/backend/llvm/expr-control.js +113 -8
  85. package/dist/backend/llvm/expr-control.js.map +1 -1
  86. package/dist/backend/llvm/expr-dispatch.js +2 -0
  87. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  88. package/dist/backend/llvm/expr-dynamic.js +244 -44
  89. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  90. package/dist/backend/llvm/expr-island.js +3 -8
  91. package/dist/backend/llvm/expr-island.js.map +1 -1
  92. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  93. package/dist/backend/llvm/expr-primitives.js +93 -36
  94. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  95. package/dist/backend/llvm/expr-primitives.test.js +51 -3
  96. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  97. package/dist/backend/llvm/expr-records.js +31 -17
  98. package/dist/backend/llvm/expr-records.js.map +1 -1
  99. package/dist/backend/llvm/expr-stream-bridges.js +96 -29
  100. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  101. package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
  102. package/dist/backend/llvm/expr-stream-callbacks.js +6 -3
  103. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
  104. package/dist/backend/llvm/integer-remainder.d.ts +11 -0
  105. package/dist/backend/llvm/integer-remainder.js +91 -0
  106. package/dist/backend/llvm/integer-remainder.js.map +1 -1
  107. package/dist/backend/llvm/layouts.d.ts +3 -1
  108. package/dist/backend/llvm/layouts.js +3 -2
  109. package/dist/backend/llvm/layouts.js.map +1 -1
  110. package/dist/backend/llvm/lazy-captures.d.ts +16 -0
  111. package/dist/backend/llvm/lazy-captures.js +96 -0
  112. package/dist/backend/llvm/lazy-captures.js.map +1 -0
  113. package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
  114. package/dist/backend/llvm/lazy-captures.test.js +78 -0
  115. package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
  116. package/dist/backend/llvm/lib-abi.js +10 -0
  117. package/dist/backend/llvm/lib-abi.js.map +1 -1
  118. package/dist/backend/llvm/lib-filesystem.js +10 -15
  119. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  120. package/dist/backend/llvm/lib-process.js +8 -8
  121. package/dist/backend/llvm/lib-process.js.map +1 -1
  122. package/dist/backend/llvm/lib-shared.js +1 -0
  123. package/dist/backend/llvm/lib-shared.js.map +1 -1
  124. package/dist/backend/llvm/local-array-reads.d.ts +5 -1
  125. package/dist/backend/llvm/local-array-reads.js +147 -26
  126. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  127. package/dist/backend/llvm/local-array-reads.test.js +85 -4
  128. package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
  129. package/dist/backend/llvm/local-union-storage.d.ts +5 -1
  130. package/dist/backend/llvm/local-union-storage.js +54 -8
  131. package/dist/backend/llvm/local-union-storage.js.map +1 -1
  132. package/dist/backend/llvm/local-union-storage.test.js +94 -6
  133. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  134. package/dist/backend/llvm/map-number-lookup.d.ts +18 -0
  135. package/dist/backend/llvm/map-number-lookup.js +62 -0
  136. package/dist/backend/llvm/map-number-lookup.js.map +1 -0
  137. package/dist/backend/llvm/map-read-lifetimes.d.ts +6 -0
  138. package/dist/backend/llvm/map-read-lifetimes.js +24 -3
  139. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  140. package/dist/backend/llvm/map-read-lifetimes.test.js +39 -20
  141. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  142. package/dist/backend/llvm/nullable-fields.d.ts +28 -0
  143. package/dist/backend/llvm/nullable-fields.js +45 -0
  144. package/dist/backend/llvm/nullable-fields.js.map +1 -0
  145. package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
  146. package/dist/backend/llvm/nullable-fields.test.js +48 -0
  147. package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
  148. package/dist/backend/llvm/nullable-unions.d.ts +68 -0
  149. package/dist/backend/llvm/nullable-unions.js +132 -0
  150. package/dist/backend/llvm/nullable-unions.js.map +1 -0
  151. package/dist/backend/llvm/publish.d.ts +58 -0
  152. package/dist/backend/llvm/publish.js +286 -0
  153. package/dist/backend/llvm/publish.js.map +1 -0
  154. package/dist/backend/llvm/rebound-parameters.d.ts +12 -0
  155. package/dist/backend/llvm/rebound-parameters.js +72 -0
  156. package/dist/backend/llvm/rebound-parameters.js.map +1 -0
  157. package/dist/backend/llvm/rebound-parameters.test.d.ts +1 -0
  158. package/dist/backend/llvm/rebound-parameters.test.js +67 -0
  159. package/dist/backend/llvm/rebound-parameters.test.js.map +1 -0
  160. package/dist/backend/llvm/reference-effects.d.ts +18 -2
  161. package/dist/backend/llvm/reference-effects.js +106 -16
  162. package/dist/backend/llvm/reference-effects.js.map +1 -1
  163. package/dist/backend/llvm/reference-effects.test.js +52 -1
  164. package/dist/backend/llvm/reference-effects.test.js.map +1 -1
  165. package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
  166. package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
  167. package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
  168. package/dist/backend/llvm/shapes.d.ts +104 -9
  169. package/dist/backend/llvm/shapes.js +356 -46
  170. package/dist/backend/llvm/shapes.js.map +1 -1
  171. package/dist/backend/llvm/shapes.test.js +139 -5
  172. package/dist/backend/llvm/shapes.test.js.map +1 -1
  173. package/dist/backend/llvm/stack-callbacks.js +2 -3
  174. package/dist/backend/llvm/stack-callbacks.js.map +1 -1
  175. package/dist/backend/llvm/stack-captures.d.ts +3 -1
  176. package/dist/backend/llvm/stack-captures.js +5 -3
  177. package/dist/backend/llvm/stack-captures.js.map +1 -1
  178. package/dist/backend/llvm/stack-unions.test.js +43 -3
  179. package/dist/backend/llvm/stack-unions.test.js.map +1 -1
  180. package/dist/backend/llvm/string-construction.d.ts +10 -0
  181. package/dist/backend/llvm/string-construction.js +42 -0
  182. package/dist/backend/llvm/string-construction.js.map +1 -1
  183. package/dist/backend/llvm/string-construction.test.js +1 -1
  184. package/dist/backend/llvm/string-key-hash.d.ts +15 -0
  185. package/dist/backend/llvm/string-key-hash.js +76 -0
  186. package/dist/backend/llvm/string-key-hash.js.map +1 -0
  187. package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
  188. package/dist/backend/llvm/string-key-hash.test.js +45 -0
  189. package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
  190. package/dist/backend/llvm/string-lifetimes.test.js +65 -15
  191. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  192. package/dist/backend/llvm/string-reads.d.ts +7 -0
  193. package/dist/backend/llvm/string-reads.js +76 -0
  194. package/dist/backend/llvm/string-reads.js.map +1 -0
  195. package/dist/backend/llvm/switch-dispatch.js +1 -1
  196. package/dist/backend/llvm/switch-dispatch.js.map +1 -1
  197. package/dist/backend/llvm/switch-dispatch.test.js +3 -3
  198. package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
  199. package/dist/backend/llvm/test-boxed-unions.d.ts +5 -0
  200. package/dist/backend/llvm/test-boxed-unions.js +13 -0
  201. package/dist/backend/llvm/test-boxed-unions.js.map +1 -0
  202. package/dist/backend/llvm/union-repr.d.ts +15 -0
  203. package/dist/backend/llvm/union-repr.js +89 -0
  204. package/dist/backend/llvm/union-repr.js.map +1 -0
  205. package/dist/backend/llvm/virtual-borrows.d.ts +31 -0
  206. package/dist/backend/llvm/virtual-borrows.js +82 -0
  207. package/dist/backend/llvm/virtual-borrows.js.map +1 -0
  208. package/dist/backend/llvm/walk-borrows.d.ts +43 -0
  209. package/dist/backend/llvm/walk-borrows.js +150 -0
  210. package/dist/backend/llvm/walk-borrows.js.map +1 -0
  211. package/dist/backend/llvm/walk-borrows.test.d.ts +1 -0
  212. package/dist/backend/llvm/walk-borrows.test.js +119 -0
  213. package/dist/backend/llvm/walk-borrows.test.js.map +1 -0
  214. package/dist/backend/llvm/walkers.d.ts +5 -1
  215. package/dist/backend/llvm/walkers.js +24 -21
  216. package/dist/backend/llvm/walkers.js.map +1 -1
  217. package/dist/backend/may-throw.d.ts +29 -1
  218. package/dist/backend/may-throw.js +349 -3
  219. package/dist/backend/may-throw.js.map +1 -1
  220. package/dist/backend/may-throw.test.js +114 -2
  221. package/dist/backend/may-throw.test.js.map +1 -1
  222. package/dist/backend/native/cache-warm.d.ts +2 -1
  223. package/dist/backend/native/cache-warm.js.map +1 -1
  224. package/dist/backend/native/contracts.d.ts +3 -2
  225. package/dist/backend/native/contracts.js.map +1 -1
  226. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  227. package/dist/backend/native/runtime-inputs.js +2 -0
  228. package/dist/backend/native/runtime-inputs.js.map +1 -1
  229. package/dist/backend/native-codegen-core.d.ts +7 -4
  230. package/dist/backend/native-codegen-core.js +14 -9
  231. package/dist/backend/native-codegen-core.js.map +1 -1
  232. package/dist/backend/native-codegen.d.ts +9 -0
  233. package/dist/backend/native-codegen.js +53 -2
  234. package/dist/backend/native-codegen.js.map +1 -1
  235. package/dist/backend/native-codegen.test.js +64 -10
  236. package/dist/backend/native-codegen.test.js.map +1 -1
  237. package/dist/backend/native-link-info-core.d.ts +3 -2
  238. package/dist/backend/native-link-info-core.js.map +1 -1
  239. package/dist/backend/native-link-info.d.ts +2 -1
  240. package/dist/backend/native-link-info.js.map +1 -1
  241. package/dist/backend/native-link-info.test.js +2 -2
  242. package/dist/backend/native-link-info.test.js.map +1 -1
  243. package/dist/backend/native-tools.d.ts +5 -1
  244. package/dist/backend/native-tools.js +3 -1
  245. package/dist/backend/native-tools.js.map +1 -1
  246. package/dist/backend/optimization.d.ts +25 -0
  247. package/dist/backend/optimization.js +21 -0
  248. package/dist/backend/optimization.js.map +1 -0
  249. package/dist/backend/optimization.test.d.ts +1 -0
  250. package/dist/backend/optimization.test.js +24 -0
  251. package/dist/backend/optimization.test.js.map +1 -0
  252. package/dist/backend/publication.d.ts +28 -0
  253. package/dist/backend/publication.js +155 -0
  254. package/dist/backend/publication.js.map +1 -0
  255. package/dist/backend/publication.test.d.ts +1 -0
  256. package/dist/backend/publication.test.js +72 -0
  257. package/dist/backend/publication.test.js.map +1 -0
  258. package/dist/backend/runtime-abi.d.ts +2 -2
  259. package/dist/backend/runtime-abi.js +2 -2
  260. package/dist/backend/runtime-pack-core.d.ts +15 -4
  261. package/dist/backend/runtime-pack-core.js +23 -12
  262. package/dist/backend/runtime-pack-core.js.map +1 -1
  263. package/dist/backend/runtime-pack-native.d.ts +7 -3
  264. package/dist/backend/runtime-pack-native.js +0 -3
  265. package/dist/backend/runtime-pack-native.js.map +1 -1
  266. package/dist/backend/runtime-pack-targets.test.js +1 -1
  267. package/dist/backend/runtime-pack.d.ts +20 -2
  268. package/dist/backend/runtime-pack.js +23 -0
  269. package/dist/backend/runtime-pack.js.map +1 -1
  270. package/dist/backend/runtime-pack.test.js +115 -2
  271. package/dist/backend/runtime-pack.test.js.map +1 -1
  272. package/dist/backend/target-diagnostics.test.js +1 -1
  273. package/dist/backend/targets.d.ts +2 -1
  274. package/dist/backend/targets.js +1 -1
  275. package/dist/backend/targets.js.map +1 -1
  276. package/dist/cli/command.js +75 -11
  277. package/dist/cli/command.js.map +1 -1
  278. package/dist/cli/host.d.ts +2 -1
  279. package/dist/cli/usage.d.ts +4 -1
  280. package/dist/cli/usage.js +13 -3
  281. package/dist/cli/usage.js.map +1 -1
  282. package/dist/compile-types.d.ts +17 -5
  283. package/dist/coverage/report.d.ts +25 -2
  284. package/dist/coverage/report.js +161 -33
  285. package/dist/coverage/report.js.map +1 -1
  286. package/dist/coverage/verdict-cache.d.ts +63 -0
  287. package/dist/coverage/verdict-cache.js +193 -0
  288. package/dist/coverage/verdict-cache.js.map +1 -0
  289. package/dist/coverage/verdict-cache.test.d.ts +1 -0
  290. package/dist/coverage/verdict-cache.test.js +52 -0
  291. package/dist/coverage/verdict-cache.test.js.map +1 -0
  292. package/dist/coverage/verdict-semantic.d.ts +2 -0
  293. package/dist/coverage/verdict-semantic.js +24 -0
  294. package/dist/coverage/verdict-semantic.js.map +1 -0
  295. package/dist/coverage/verdict-startup.d.ts +15 -0
  296. package/dist/coverage/verdict-startup.js +66 -0
  297. package/dist/coverage/verdict-startup.js.map +1 -0
  298. package/dist/diagnostics/diagnostic.d.ts +29 -1
  299. package/dist/diagnostics/diagnostic.js +84 -12
  300. package/dist/diagnostics/diagnostic.js.map +1 -1
  301. package/dist/diagnostics/envelope.d.ts +130 -0
  302. package/dist/diagnostics/envelope.js +257 -0
  303. package/dist/diagnostics/envelope.js.map +1 -0
  304. package/dist/diagnostics/envelope.test.d.ts +1 -0
  305. package/dist/diagnostics/envelope.test.js +91 -0
  306. package/dist/diagnostics/envelope.test.js.map +1 -0
  307. package/dist/diagnostics/render.d.ts +3 -0
  308. package/dist/diagnostics/render.js +13 -2
  309. package/dist/diagnostics/render.js.map +1 -1
  310. package/dist/executable/executable-cache.d.ts +2 -2
  311. package/dist/executable/executable-cache.js +7 -4
  312. package/dist/executable/executable-cache.js.map +1 -1
  313. package/dist/executable/executable-cache.test.js +20 -0
  314. package/dist/executable/executable-cache.test.js.map +1 -1
  315. package/dist/executable/prepare.d.ts +4 -0
  316. package/dist/executable/prepare.js +7 -1
  317. package/dist/executable/prepare.js.map +1 -1
  318. package/dist/frontend/analysis.js +1 -0
  319. package/dist/frontend/analysis.js.map +1 -1
  320. package/dist/frontend/lowering/abstract-equality.js +5 -49
  321. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  322. package/dist/frontend/lowering/array-values.d.ts +30 -0
  323. package/dist/frontend/lowering/array-values.js +246 -1
  324. package/dist/frontend/lowering/array-values.js.map +1 -1
  325. package/dist/frontend/lowering/builtins/errors.js +17 -2
  326. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  327. package/dist/frontend/lowering/builtins/numbers.js +29 -1
  328. package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
  329. package/dist/frontend/lowering/builtins/process.d.ts +10 -17
  330. package/dist/frontend/lowering/builtins/process.js +66 -29
  331. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  332. package/dist/frontend/lowering/builtins/workers.js +4 -2
  333. package/dist/frontend/lowering/builtins/workers.js.map +1 -1
  334. package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
  335. package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
  336. package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
  337. package/dist/frontend/lowering/class-assertions.d.ts +12 -0
  338. package/dist/frontend/lowering/class-assertions.js +229 -5
  339. package/dist/frontend/lowering/class-assertions.js.map +1 -1
  340. package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
  341. package/dist/frontend/lowering/class-callbacks.js +18 -5
  342. package/dist/frontend/lowering/class-callbacks.js.map +1 -1
  343. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
  344. package/dist/frontend/lowering/class-dynamic-dispatch.js +12 -6
  345. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  346. package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
  347. package/dist/frontend/lowering/class-method-mutations.js +472 -0
  348. package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
  349. package/dist/frontend/lowering/class-method-values.js +25 -5
  350. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  351. package/dist/frontend/lowering/class-prototypes.js +8 -2
  352. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  353. package/dist/frontend/lowering/class-unions.d.ts +16 -0
  354. package/dist/frontend/lowering/class-unions.js +127 -0
  355. package/dist/frontend/lowering/class-unions.js.map +1 -0
  356. package/dist/frontend/lowering/coercions/builders.js +8 -1
  357. package/dist/frontend/lowering/coercions/builders.js.map +1 -1
  358. package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
  359. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  360. package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
  361. package/dist/frontend/lowering/coercions/identity.js +26 -0
  362. package/dist/frontend/lowering/coercions/identity.js.map +1 -0
  363. package/dist/frontend/lowering/coercions/state.d.ts +6 -0
  364. package/dist/frontend/lowering/coercions/state.js +2 -0
  365. package/dist/frontend/lowering/coercions/state.js.map +1 -1
  366. package/dist/frontend/lowering/coercions/structural.js +9 -6
  367. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  368. package/dist/frontend/lowering/coercions/unions.d.ts +8 -0
  369. package/dist/frontend/lowering/coercions/unions.js +67 -2
  370. package/dist/frontend/lowering/coercions/unions.js.map +1 -1
  371. package/dist/frontend/lowering/collation-repertoire.d.ts +1 -0
  372. package/dist/frontend/lowering/collation-repertoire.js +19 -0
  373. package/dist/frontend/lowering/collation-repertoire.js.map +1 -0
  374. package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
  375. package/dist/frontend/lowering/collection-narrowing.js +31 -0
  376. package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
  377. package/dist/frontend/lowering/construction-escapes.d.ts +38 -0
  378. package/dist/frontend/lowering/construction-escapes.js +146 -0
  379. package/dist/frontend/lowering/construction-escapes.js.map +1 -0
  380. package/dist/frontend/lowering/construction-escapes.test.d.ts +1 -0
  381. package/dist/frontend/lowering/construction-escapes.test.js +150 -0
  382. package/dist/frontend/lowering/construction-escapes.test.js.map +1 -0
  383. package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
  384. package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
  385. package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
  386. package/dist/frontend/lowering/containers/array-callbacks.d.ts +1 -1
  387. package/dist/frontend/lowering/containers/array-callbacks.js +416 -65
  388. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  389. package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
  390. package/dist/frontend/lowering/containers/array-concat.js +130 -0
  391. package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
  392. package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
  393. package/dist/frontend/lowering/containers/array-construction.js +110 -5
  394. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  395. package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
  396. package/dist/frontend/lowering/containers/array-methods.js +274 -144
  397. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  398. package/dist/frontend/lowering/containers/callback-arguments.js +43 -1
  399. package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
  400. package/dist/frontend/lowering/containers/collection-methods.js +10 -1
  401. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  402. package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
  403. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  404. package/dist/frontend/lowering/containers/string-and-regexp.js +7 -63
  405. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  406. package/dist/frontend/lowering/cycle-initialization.d.ts +46 -0
  407. package/dist/frontend/lowering/cycle-initialization.js +303 -0
  408. package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
  409. package/dist/frontend/lowering/divergences.d.ts +9 -0
  410. package/dist/frontend/lowering/divergences.js +630 -0
  411. package/dist/frontend/lowering/divergences.js.map +1 -0
  412. package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
  413. package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
  414. package/dist/frontend/lowering/expressions/object-literals.js +178 -34
  415. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  416. package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
  417. package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
  418. package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
  419. package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
  420. package/dist/frontend/lowering/iterator-adapters.js +605 -0
  421. package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
  422. package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
  423. package/dist/frontend/lowering/lower-array-sort.js +44 -5
  424. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  425. package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
  426. package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
  427. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
  428. package/dist/frontend/lowering/lower-assert.js +7 -0
  429. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  430. package/dist/frontend/lowering/lower-builtin-values.js +1 -0
  431. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  432. package/dist/frontend/lowering/lower-calls.d.ts +8 -3
  433. package/dist/frontend/lowering/lower-calls.js +388 -278
  434. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  435. package/dist/frontend/lowering/lower-classes.d.ts +6 -0
  436. package/dist/frontend/lowering/lower-classes.js +117 -65
  437. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  438. package/dist/frontend/lowering/lower-exprs.d.ts +22 -2
  439. package/dist/frontend/lowering/lower-exprs.js +811 -254
  440. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  441. package/dist/frontend/lowering/lower-functions.js +32 -19
  442. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  443. package/dist/frontend/lowering/lower-generators.d.ts +19 -13
  444. package/dist/frontend/lowering/lower-generators.js +67 -44
  445. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  446. package/dist/frontend/lowering/lower-inspect.js +29 -4
  447. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  448. package/dist/frontend/lowering/lower-island.d.ts +1 -1
  449. package/dist/frontend/lowering/lower-island.js +24 -7
  450. package/dist/frontend/lowering/lower-island.js.map +1 -1
  451. package/dist/frontend/lowering/lower-modules.js +100 -3
  452. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  453. package/dist/frontend/lowering/lower-stmts.js +82 -64
  454. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  455. package/dist/frontend/lowering/lowerer.d.ts +115 -2
  456. package/dist/frontend/lowering/lowerer.js +1266 -88
  457. package/dist/frontend/lowering/lowerer.js.map +1 -1
  458. package/dist/frontend/lowering/native-ffi.js +3 -1
  459. package/dist/frontend/lowering/native-ffi.js.map +1 -1
  460. package/dist/frontend/lowering/runtime-optional-bounds.d.ts +19 -0
  461. package/dist/frontend/lowering/runtime-optional-bounds.js +354 -0
  462. package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -0
  463. package/dist/frontend/lowering/runtime-optional-bounds.test.d.ts +1 -0
  464. package/dist/frontend/lowering/runtime-optional-bounds.test.js +66 -0
  465. package/dist/frontend/lowering/runtime-optional-bounds.test.js.map +1 -0
  466. package/dist/frontend/lowering/runtime-optional-elements.d.ts +117 -0
  467. package/dist/frontend/lowering/runtime-optional-elements.js +738 -0
  468. package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -0
  469. package/dist/frontend/lowering/runtime-optional-guards.d.ts +36 -0
  470. package/dist/frontend/lowering/runtime-optional-guards.js +375 -0
  471. package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -0
  472. package/dist/frontend/lowering/runtime-optional-guards.test.d.ts +1 -0
  473. package/dist/frontend/lowering/runtime-optional-guards.test.js +92 -0
  474. package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -0
  475. package/dist/frontend/lowering/runtime-optional-ownership.d.ts +63 -0
  476. package/dist/frontend/lowering/runtime-optional-ownership.js +382 -0
  477. package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -0
  478. package/dist/frontend/lowering/runtime-optional-provenance.d.ts +16 -0
  479. package/dist/frontend/lowering/runtime-optional-provenance.js +41 -0
  480. package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
  481. package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
  482. package/dist/frontend/lowering/strict-equality.d.ts +9 -0
  483. package/dist/frontend/lowering/strict-equality.js +116 -0
  484. package/dist/frontend/lowering/strict-equality.js.map +1 -0
  485. package/dist/frontend/lowering/string-index-bounds.d.ts +36 -0
  486. package/dist/frontend/lowering/string-index-bounds.js +537 -0
  487. package/dist/frontend/lowering/string-index-bounds.js.map +1 -0
  488. package/dist/frontend/lowering/string-index-bounds.test.d.ts +1 -0
  489. package/dist/frontend/lowering/string-index-bounds.test.js +223 -0
  490. package/dist/frontend/lowering/string-index-bounds.test.js.map +1 -0
  491. package/dist/frontend/lowering/surfaces.js +3 -0
  492. package/dist/frontend/lowering/surfaces.js.map +1 -1
  493. package/dist/frontend/lowering/union-comparison.d.ts +5 -0
  494. package/dist/frontend/lowering/union-comparison.js +47 -0
  495. package/dist/frontend/lowering/union-comparison.js.map +1 -0
  496. package/dist/frontend/lowering/union-narrow.d.ts +2 -0
  497. package/dist/frontend/lowering/union-narrow.js +10 -6
  498. package/dist/frontend/lowering/union-narrow.js.map +1 -1
  499. package/dist/frontend/program-analysis.d.ts +10 -0
  500. package/dist/frontend/program-analysis.js +7 -0
  501. package/dist/frontend/program-analysis.js.map +1 -1
  502. package/dist/frontend/program.d.ts +63 -2
  503. package/dist/frontend/program.js +1038 -61
  504. package/dist/frontend/program.js.map +1 -1
  505. package/dist/frontend/program.test.js +122 -6
  506. package/dist/frontend/program.test.js.map +1 -1
  507. package/dist/frontend/resolve.d.ts +6 -0
  508. package/dist/frontend/resolve.js +14 -0
  509. package/dist/frontend/resolve.js.map +1 -1
  510. package/dist/frontend/threads-import.d.ts +5 -0
  511. package/dist/frontend/threads-import.js +21 -0
  512. package/dist/frontend/threads-import.js.map +1 -0
  513. package/dist/frontend/type-mapper.d.ts +4 -1
  514. package/dist/frontend/type-mapper.js +161 -20
  515. package/dist/frontend/type-mapper.js.map +1 -1
  516. package/dist/frontend/type-mapper.test.js +15 -3
  517. package/dist/frontend/type-mapper.test.js.map +1 -1
  518. package/dist/frontend/worker-target.d.ts +4 -0
  519. package/dist/frontend/worker-target.js +8 -1
  520. package/dist/frontend/worker-target.js.map +1 -1
  521. package/dist/index.d.ts +6 -1
  522. package/dist/index.js +70 -16
  523. package/dist/index.js.map +1 -1
  524. package/dist/ir/analysis.d.ts +3 -1
  525. package/dist/ir/analysis.js +4 -0
  526. package/dist/ir/analysis.js.map +1 -1
  527. package/dist/ir/build.d.ts +5 -0
  528. package/dist/ir/build.js +7 -0
  529. package/dist/ir/build.js.map +1 -1
  530. package/dist/ir/builtin-signatures.d.ts +1 -1
  531. package/dist/ir/builtin-signatures.js +5 -3
  532. package/dist/ir/builtin-signatures.js.map +1 -1
  533. package/dist/ir/constant-tables.test.js +1 -1
  534. package/dist/ir/initializer-bindings.test.js +1 -1
  535. package/dist/ir/int32-slots.d.ts +72 -0
  536. package/dist/ir/int32-slots.js +837 -0
  537. package/dist/ir/int32-slots.js.map +1 -0
  538. package/dist/ir/int32-slots.test.d.ts +1 -0
  539. package/dist/ir/int32-slots.test.js +222 -0
  540. package/dist/ir/int32-slots.test.js.map +1 -0
  541. package/dist/ir/integer-ranges.d.ts +19 -3
  542. package/dist/ir/integer-ranges.js +168 -23
  543. package/dist/ir/integer-ranges.js.map +1 -1
  544. package/dist/ir/integer-ranges.test.js +74 -2
  545. package/dist/ir/integer-ranges.test.js.map +1 -1
  546. package/dist/ir/ir.d.ts +101 -20
  547. package/dist/ir/ir.js +20 -6
  548. package/dist/ir/ir.js.map +1 -1
  549. package/dist/ir/scalar-records.test.js +1 -1
  550. package/dist/ir/serialize.d.ts +1 -1
  551. package/dist/ir/serialize.js +3 -3
  552. package/dist/ir/serialize.js.map +1 -1
  553. package/dist/ir/traverse.js +8 -0
  554. package/dist/ir/traverse.js.map +1 -1
  555. package/dist/ir/validate.js +139 -22
  556. package/dist/ir/validate.js.map +1 -1
  557. package/dist/ir/validate.test.js +308 -8
  558. package/dist/ir/validate.test.js.map +1 -1
  559. package/dist/library/fence-eval.test.js +1 -1
  560. package/dist/library/int-infer.test.js +4 -4
  561. package/dist/library/library-cache.test.js +5 -5
  562. package/dist/library/library-profile.d.ts +2 -1
  563. package/dist/library/library-profile.js +4 -3
  564. package/dist/library/library-profile.js.map +1 -1
  565. package/dist/native/cache.d.ts +3 -0
  566. package/dist/native/cache.js +49 -1
  567. package/dist/native/cache.js.map +1 -1
  568. package/dist/native/cache.test.js +21 -1
  569. package/dist/native/cache.test.js.map +1 -1
  570. package/dist/native/cli.js +1 -1
  571. package/dist/native/cli.js.map +1 -1
  572. package/dist/native/compiler.d.ts +5 -0
  573. package/dist/native/compiler.js +51 -4
  574. package/dist/native/compiler.js.map +1 -1
  575. package/dist/native/compiler.test.js +2 -2
  576. package/dist/native/library.d.ts +2 -1
  577. package/dist/native/library.js.map +1 -1
  578. package/dist/native/prepare.d.ts +4 -0
  579. package/dist/native/prepare.js +28 -3
  580. package/dist/native/prepare.js.map +1 -1
  581. package/dist/native/sanitizer.d.ts +3 -2
  582. package/dist/native/sanitizer.js +3 -13
  583. package/dist/native/sanitizer.js.map +1 -1
  584. package/dist/startup-cache.d.ts +2 -0
  585. package/dist/startup-cache.js +2 -0
  586. package/dist/startup-cache.js.map +1 -1
  587. package/package.json +20 -20
  588. package/surface-manifest.json +8 -2
@@ -1,7 +1,10 @@
1
1
  import { boolLit, countedFor, numLit, varRef } from "../../../ir/build.js";
2
+ import { transformStmtList } from "../../../ir/traverse.js";
2
3
  import { InternalCompilerError } from "../../../errors.js";
4
+ import { canAssertClassValue, checkedClassAssertion } from "../class-assertions.js";
3
5
  import * as ts from "../../ts7/adapter.js";
4
- import { BOOL, DYN, F64, STRING, UNDEFINED_T, VOID, arrayOf, funcOf, isUnitType, typeEquals, } from "../../../ir/ir.js";
6
+ import { PoisonError } from "../lowerer.js";
7
+ import { BOOL, DYN, F64, STRING, UNDEFINED_T, VOID, arrayOf, funcOf, isSortValuesElement, isUnitType, typeEquals, } from "../../../ir/ir.js";
5
8
  import { isJsSourceFile, locOf } from "../../program.js";
6
9
  import { buildArraySortFn } from "../lower-array-sort.js";
7
10
  import { arrayIndexPresent, arrayValueRead, arrayValueStore, arrayValueType, currentArrayIndexPresent, } from "../array-values.js";
@@ -30,7 +33,8 @@ export function lowerArrayHofCall(lowerer, call, access, method, elem) {
30
33
  ts.isIdentifier(argNode) &&
31
34
  argNode.text === "Boolean" &&
32
35
  lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(argNode) ?? undefined);
33
- const valueT = arrayValueType(lowerer, elem);
36
+ const present = !booleanFilter && presentElements(lowerer, call, elem);
37
+ const valueT = callbackValueType(lowerer, elem, present);
34
38
  if (booleanFilter) {
35
39
  if (valueT.kind === "union")
36
40
  lowerer.requireTruthyUnion(valueT.unionId, argNode);
@@ -70,9 +74,19 @@ export function lowerArrayHofCall(lowerer, call, access, method, elem) {
70
74
  const outElem = method === "filter"
71
75
  ? filterResultElem(lowerer, call, argNode, elem, valueT, booleanFilter)
72
76
  : callbackArrayElement(lowerer, call, fnRet);
73
- const helper = arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem);
77
+ // A filter that re-tags its elements keeps the single union-typed visit.
78
+ const fast = present || booleanFilter || (method === "filter" && !typeEquals(outElem, elem))
79
+ ? null
80
+ : lowerFastCallback(lowerer, argNode, [valueT], 0, elem, arrayOf(elem), callback);
81
+ const helper = arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
74
82
  const resultType = method === "map" || method === "filter" ? arrayOf(outElem) : VOID;
75
- return { kind: "call", callee: helper, args: [receiver, fnArg], type: resultType, loc };
83
+ return {
84
+ kind: "call",
85
+ callee: helper,
86
+ args: [receiver, fnArg, ...(fast ? [fast] : [])],
87
+ type: resultType,
88
+ loc,
89
+ };
76
90
  }
77
91
  /** The checker-selected element of a filter result, with the same trust
78
92
  * boundary as the historical narrowing filter: an inferred inline type
@@ -112,13 +126,15 @@ function filterResultElem(lowerer, call, argNode, elem, valueT, booleanFilter) {
112
126
  `unchecked assertion nothing validates at runtime — ${annotateEscape})`);
113
127
  }
114
128
  }
115
- if (valueT.kind !== "union" || lowerer.armTag(valueT.unionId, outElem) < 0) {
129
+ const classRefinement = !booleanFilter && outElem.kind === "object" && canAssertClassValue(lowerer, valueT, outElem);
130
+ if (!classRefinement &&
131
+ (valueT.kind !== "union" || lowerer.armTag(valueT.unionId, outElem) < 0)) {
116
132
  const multiArm = outElem.kind === "union";
117
133
  lowerer.unsupported("SC1090", call, `'.filter' narrowing '${lowerer.fmt(elem)}' elements to ` +
118
134
  `${multiArm ? `the multi-arm '${lowerer.fmt(outElem)}'` : `'${lowerer.fmt(outElem)}'`} ` +
119
135
  `(${multiArm ? "only a SINGLE arm re-tags" : "only a single runtime arm re-tags"} — ${annotateEscape})`);
120
136
  }
121
- if (booleanFilter) {
137
+ if (booleanFilter && valueT.kind === "union") {
122
138
  const arms = lowerer.unions.get(valueT.unionId)?.arms ?? [];
123
139
  if (arms.some((arm) => !typeEquals(arm, outElem) && !isUnitType(arm))) {
124
140
  lowerer.unsupported("SC1090", call, `'.filter(Boolean)' narrowing '${lowerer.fmt(elem)}' to '${lowerer.fmt(outElem)}' ` +
@@ -194,18 +210,214 @@ function filterCond(call, fnRet, loc) {
194
210
  // the runtime's kind-aware ToBoolean.
195
211
  return { kind: "toBool", operand: call, type: BOOL, loc };
196
212
  }
213
+ /** Nested HOFs inside a fast lowering keep their single union visit, so
214
+ * duplication stays linear in nesting depth. */
215
+ let fastLoweringDepth = 0;
216
+ /** Array reads widen elements with undefined so holes and present
217
+ * undefined stay observable, which makes every callback parameter a boxed
218
+ * `T | undefined`. For an inline arrow over a plain element type, lower the
219
+ * callback a second time with the element type itself. The helper then
220
+ * splits each visit on the element state: a present value calls this fast
221
+ * closure with the plain element (no union box, no per-use undefined
222
+ * test), and a hole or present undefined calls the original closure with
223
+ * the undefined arm. Both closures share the same capture boxes and body,
224
+ * so every observable effect is the same; arrows have no own `this`,
225
+ * `arguments` or self binding that could tell the two apart. Any refusal
226
+ * in the second lowering is discarded and keeps the single visit. */
227
+ function lowerFastCallback(lowerer, argNode, lead, elemIndex, elem, arrT, slow, bindUntyped = false, expectedReturn) {
228
+ const valueT = lead[elemIndex];
229
+ if (fastLoweringDepth > 0 ||
230
+ slow.arity <= elemIndex ||
231
+ !ts.isArrowFunction(argNode) ||
232
+ isJsSourceFile(argNode.getSourceFile()) ||
233
+ valueT?.kind !== "union" ||
234
+ typeEquals(valueT, elem) ||
235
+ elem.kind === "union" ||
236
+ elem.kind === "dyn" ||
237
+ elem.kind === "jsval" ||
238
+ isUnitType(elem))
239
+ return null;
240
+ const fastLead = lead.slice();
241
+ fastLead[elemIndex] = elem;
242
+ // The optional-read prepass binds an unannotated element parameter to
243
+ // the array's runtime value type. Rebind it to the plain element for
244
+ // this lowering only.
245
+ const param = argNode.parameters[elemIndex];
246
+ if (!param || param.initializer || param.dotDotDotToken || !ts.isIdentifier(param.name))
247
+ return null;
248
+ const symbol = param.type ? undefined : lowerer.checker.getSymbolAtLocation(param.name);
249
+ const previousBinding = symbol ? lowerer.runtimeOptionalBindingTypes.get(symbol) : undefined;
250
+ if (symbol)
251
+ lowerer.runtimeOptionalBindingTypes.set(symbol, elem);
252
+ const sink = [];
253
+ const previousSink = lowerer.diagSink;
254
+ lowerer.diagSink = sink;
255
+ fastLoweringDepth++;
256
+ let fast;
257
+ try {
258
+ fast = lowerArrayCallback(lowerer, argNode, fastLead, arrT, bindUntyped, expectedReturn);
259
+ }
260
+ catch (e) {
261
+ if (e instanceof PoisonError)
262
+ return null;
263
+ throw e;
264
+ }
265
+ finally {
266
+ fastLoweringDepth--;
267
+ lowerer.diagSink = previousSink;
268
+ if (symbol) {
269
+ if (previousBinding === undefined)
270
+ lowerer.runtimeOptionalBindingTypes.delete(symbol);
271
+ else
272
+ lowerer.runtimeOptionalBindingTypes.set(symbol, previousBinding);
273
+ }
274
+ }
275
+ const fastT = fast.fnArg.type;
276
+ const slowT = slow.fnArg.type;
277
+ if (fast.fnArg.kind !== "closure" ||
278
+ fast.arity !== slow.arity ||
279
+ !typeEquals(fastT.ret, slowT.ret) ||
280
+ !fastT.params.every((param, i) => typeEquals(param, i === elemIndex ? elem : slowT.params[i])))
281
+ return null;
282
+ return fast.fnArg;
283
+ }
284
+ /** `a[i]` holds a value (array state 1): neither a hole nor a present
285
+ * undefined. */
286
+ function presentValue(arr, index, loc) {
287
+ return {
288
+ kind: "bin",
289
+ op: "===",
290
+ left: { kind: "arrayState", arr, index, type: F64, loc },
291
+ right: numLit(1, loc),
292
+ type: BOOL,
293
+ loc,
294
+ };
295
+ }
296
+ /** Route a helper's callback calls through the split visit: every
297
+ * `f(<arrayValueRead a[i]>, ...)` becomes
298
+ * `state(a, i) === 1 ? fast(a[i], ...) : f(undefined, ...)`. The read is
299
+ * the call's only effectful operand (the rest are the loop's index and
300
+ * array locals), so evaluation order is unchanged. The fast closure is an
301
+ * extra trailing parameter. */
302
+ function withFastCallback(fn, fastT, elem) {
303
+ if (!fastT)
304
+ return fn;
305
+ const isValueRead = (e) => e.kind === "ternary" &&
306
+ e.cond.kind === "bin" &&
307
+ e.cond.op === "===" &&
308
+ e.cond.left.kind === "arrayState" &&
309
+ e.cond.right.kind === "numLit" &&
310
+ e.cond.right.value === 1;
311
+ const split = (e) => {
312
+ if (e.kind !== "callValue" || e.callee.kind !== "varRef" || e.callee.localId !== "f.0")
313
+ return null;
314
+ const at = e.args.findIndex(isValueRead);
315
+ if (at < 0)
316
+ return null;
317
+ const read = e.args[at];
318
+ if (read.kind !== "ternary")
319
+ return null;
320
+ const condition = read.cond;
321
+ if (condition.kind !== "bin")
322
+ return null;
323
+ const state = condition.left;
324
+ if (state.kind !== "arrayState")
325
+ return null;
326
+ const fastArgs = e.args.slice();
327
+ fastArgs[at] = {
328
+ kind: "arrayGet",
329
+ arr: state.arr,
330
+ index: state.index,
331
+ type: elem,
332
+ loc: read.loc,
333
+ };
334
+ const slowArgs = e.args.slice();
335
+ slowArgs[at] = read.else_;
336
+ return {
337
+ cond: read.cond,
338
+ fast: { ...e, callee: varRef("fast.0", fastT, e.callee.loc), args: fastArgs },
339
+ slow: { ...e, args: slowArgs },
340
+ };
341
+ };
342
+ const body = transformStmtList(fn.body, {
343
+ stmt: (stmt) => {
344
+ if (stmt.kind !== "exprStmt")
345
+ return stmt;
346
+ const parts = split(stmt.expr);
347
+ if (!parts)
348
+ return stmt;
349
+ return {
350
+ kind: "if",
351
+ cond: parts.cond,
352
+ then: [{ kind: "exprStmt", expr: parts.fast, loc: stmt.loc }],
353
+ else_: [{ kind: "exprStmt", expr: parts.slow, loc: stmt.loc }],
354
+ loc: stmt.loc,
355
+ };
356
+ },
357
+ expr: (expr) => {
358
+ const parts = split(expr);
359
+ if (!parts)
360
+ return expr;
361
+ return {
362
+ kind: "ternary",
363
+ cond: parts.cond,
364
+ then: parts.fast,
365
+ else_: parts.slow,
366
+ type: expr.type,
367
+ loc: expr.loc,
368
+ };
369
+ },
370
+ });
371
+ return {
372
+ ...fn,
373
+ params: [...fn.params, { localId: "fast.0", name: "fast", type: fastT }],
374
+ locals: [...fn.locals, { id: "fast.0", name: "fast", type: fastT, mutable: true }],
375
+ body,
376
+ };
377
+ }
378
+ /** The interning suffix for a callback argument. A literal closure (an
379
+ * inline arrow or function expression) gets a helper of its own, so the
380
+ * helper's only incoming callback is one known function: the backend's
381
+ * constant-callback census then calls it directly and LLVM can inline the
382
+ * callback into the loop (TurboFan's builtin+callback inlining). Callback
383
+ * values keep the shared, type-interned helper. */
384
+ function callbackSite(fnArg) {
385
+ return fnArg.kind === "closure" ? `@${fnArg.fnName}` : "";
386
+ }
387
+ /** The optional-read analysis proved this call's receiver never holds an
388
+ * explicit undefined (or, for the find family, a hole): its callback takes
389
+ * the element type itself, read without a state test. A missing value the
390
+ * proof excluded would make the element read trap instead of producing a
391
+ * wrong value. */
392
+ function presentElements(lowerer, call, elem) {
393
+ return (lowerer.presentElementCalls.has(call) &&
394
+ elem.kind !== "dyn" &&
395
+ elem.kind !== "jsval" &&
396
+ elem.kind !== "void" &&
397
+ !isUnitType(elem));
398
+ }
399
+ /** The value a helper passes its callback for one visited index. */
400
+ function callbackValueType(lowerer, elem, present) {
401
+ return present ? elem : arrayValueType(lowerer, elem);
402
+ }
403
+ function callbackValueRead(lowerer, arr, index, elem, present, loc) {
404
+ return present
405
+ ? { kind: "arrayGet", arr, index, type: elem, loc }
406
+ : arrayValueRead(lowerer, arr, index, elem, loc);
407
+ }
197
408
  /** Interned synthetic loop function for one (method, elem, fnRet, arity)
198
409
  * combo. Named `%arr.<method>.<n>` ('%' keeps it out of the user
199
410
  * namespace); rides `liftedFns` into the module like a lifted lambda (it
200
411
  * is a plain function — no captures). */
201
- function arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem = fnRet) {
202
- const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}:${typeKey(outElem)}`;
412
+ function arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem = fnRet, site = "", fastT = null, present = false) {
413
+ const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}:${typeKey(outElem)}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
203
414
  const existing = lowerer.arrHofHelpers.get(key);
204
415
  if (existing)
205
416
  return existing;
206
417
  const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
207
418
  lowerer.arrHofHelpers.set(key, name);
208
- lowerer.liftedFns.push(buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem));
419
+ const fn = buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem, fastT, present);
420
+ lowerer.liftedFns.push(fastT ? withFastCallback(fn, fastT, elem) : fn);
209
421
  return name;
210
422
  }
211
423
  /** The TS 5.2+ callable-union array rule: a `T[] | U[]` receiver exposes
@@ -363,14 +575,14 @@ function arrayUnionHofHelper(lowerer, method, receiverT, arrays, callbackT, arit
363
575
  * `arity` is the callback's declared parameter count (1–3): the loop
364
576
  * passes the index and the receiver itself after the element when the
365
577
  * callback names them, exactly the arguments JS supplies. */
366
- function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem) {
578
+ function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem, fastT = null, present = false) {
367
579
  const arrT = arrayOf(elem);
368
- const valueT = arrayValueType(lowerer, elem);
369
- const fnT = funcOf([arrayValueType(lowerer, elem), F64, arrT].slice(0, arity), fnRet);
580
+ const valueT = callbackValueType(lowerer, elem, present);
581
+ const fnT = funcOf([valueT, F64, arrT].slice(0, arity), fnRet);
370
582
  const locals = arrayCallbackLocals(arrT, fnT);
371
583
  const params = arrayCallbackParams(arrT, fnT);
372
584
  const callF = (arg) => callArrayCallback(arrT, fnT, fnRet, arity, arg, loc);
373
- const getElem = arrayValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, loc);
585
+ const getElem = callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc);
374
586
  const hasElem = {
375
587
  kind: "arrayHas",
376
588
  arr: varRef("a.0", arrT, loc),
@@ -428,22 +640,111 @@ function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem
428
640
  { kind: "return", value: varRef("out.0", outT, loc), loc },
429
641
  ];
430
642
  }
643
+ else if (method === "filter" && fastT) {
644
+ // Split visit (outElem === elem): a present value goes to the fast
645
+ // callback as a plain element and is kept as-is; a present undefined
646
+ // goes to the original callback and is kept as undefined.
647
+ const outT = arrayOf(outElem);
648
+ locals.push({ id: "out.0", name: "out", type: outT, mutable: false }, { id: "e.0", name: "e", type: elem, mutable: false });
649
+ returnType = outT;
650
+ const a = varRef("a.0", arrT, loc);
651
+ const i = varRef("i.0", F64, loc);
652
+ const outLength = {
653
+ kind: "arrIntrinsic",
654
+ method: "length",
655
+ receiver: varRef("out.0", outT, loc),
656
+ args: [],
657
+ type: F64,
658
+ loc,
659
+ };
660
+ const missing = getElem.else_;
661
+ const callFast = (arg) => ({
662
+ kind: "callValue",
663
+ callee: varRef("fast.0", fastT, loc),
664
+ args: [arg, i, a].slice(0, arity),
665
+ type: fnRet,
666
+ loc,
667
+ });
668
+ body = [
669
+ {
670
+ kind: "varDecl",
671
+ localId: "out.0",
672
+ init: { kind: "arrayLit", elems: [], type: outT, loc },
673
+ loc,
674
+ },
675
+ readLen,
676
+ forLoop([
677
+ {
678
+ kind: "if",
679
+ cond: hasElem,
680
+ then: [
681
+ {
682
+ kind: "if",
683
+ cond: presentValue(a, i, loc),
684
+ then: [
685
+ {
686
+ kind: "varDecl",
687
+ localId: "e.0",
688
+ init: { kind: "arrayGet", arr: a, index: i, type: elem, loc },
689
+ loc,
690
+ },
691
+ {
692
+ kind: "if",
693
+ cond: filterCond(callFast(varRef("e.0", elem, loc)), fnRet, loc),
694
+ then: [
695
+ arrayValueStore(lowerer, varRef("out.0", outT, loc), outLength, varRef("e.0", elem, loc), outElem, loc),
696
+ ],
697
+ else_: null,
698
+ loc,
699
+ },
700
+ ],
701
+ else_: [
702
+ {
703
+ kind: "if",
704
+ cond: filterCond(callF(missing), fnRet, loc),
705
+ then: [
706
+ {
707
+ kind: "arraySetUndefined",
708
+ arr: varRef("out.0", outT, loc),
709
+ index: outLength,
710
+ loc,
711
+ },
712
+ ],
713
+ else_: null,
714
+ loc,
715
+ },
716
+ ],
717
+ loc,
718
+ },
719
+ ],
720
+ else_: null,
721
+ loc,
722
+ },
723
+ ]),
724
+ { kind: "return", value: varRef("out.0", outT, loc), loc },
725
+ ];
726
+ }
431
727
  else if (method === "filter") {
432
728
  const outT = arrayOf(outElem);
433
729
  locals.push({ id: "out.0", name: "out", type: outT, mutable: false }, { id: "v.0", name: "v", type: valueT, mutable: false });
434
730
  returnType = outT;
731
+ const classView = !typeEquals(outElem, elem) && outElem.kind === "object"
732
+ ? checkedClassAssertion(lowerer, varRef("v.0", valueT, loc), outElem, loc)
733
+ : null;
435
734
  const retained = typeEquals(outElem, elem)
436
735
  ? varRef("v.0", valueT, loc)
437
- : valueT.kind === "union"
438
- ? {
439
- kind: "unionNarrow",
440
- unionId: valueT.unionId,
441
- tag: lowerer.armTag(valueT.unionId, outElem),
442
- value: varRef("v.0", valueT, loc),
443
- type: outElem,
444
- loc,
445
- }
446
- : varRef("v.0", valueT, loc);
736
+ : classView !== null
737
+ ? classView
738
+ : valueT.kind === "union"
739
+ ? {
740
+ kind: "unionNarrow",
741
+ unionId: valueT.unionId,
742
+ tag: lowerer.armTag(valueT.unionId, outElem),
743
+ value: varRef("v.0", valueT, loc),
744
+ type: outElem,
745
+ loc,
746
+ }
747
+ : varRef("v.0", valueT, loc);
447
748
  body = [
448
749
  {
449
750
  kind: "varDecl",
@@ -519,7 +820,12 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
519
820
  const argNode = call.arguments[0];
520
821
  if (!argNode)
521
822
  lowerer.unsupported("SC1090", call, "this call form"); // tsc-guarded
522
- const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], arrT, bindUntyped);
823
+ // find's result must be reachable from the element itself; a predicate
824
+ // that narrows to another layout keeps the optional element visit.
825
+ const present = presentElements(lowerer, call, elem) &&
826
+ ((method !== "find" && method !== "findLast") ||
827
+ (!bindUntyped && lowerer.coercibleValue(elem, lowerer.irTypeOf(call))));
828
+ const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [callbackValueType(lowerer, elem, present)], arrT, bindUntyped);
523
829
  // JS takes the ToBoolean of the predicate's result — allowed wherever
524
830
  // that ToBoolean has a static answer (bool passes through; f64/string
525
831
  // by value; a truthy-answerable union by its arm — the
@@ -539,13 +845,17 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
539
845
  method === "every" ||
540
846
  method === "findIndex" ||
541
847
  method === "findLastIndex") {
848
+ const fast = present
849
+ ? null
850
+ : lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, { fnArg, arity }, bindUntyped);
851
+ const fastT = fast?.type ?? null;
542
852
  const helper = method === "findIndex" || method === "findLastIndex"
543
- ? findIndexHelper(lowerer, elem, fnRet, arity, last, loc)
544
- : someEveryHelper(lowerer, method, elem, fnRet, arity, loc);
853
+ ? findIndexHelper(lowerer, elem, fnRet, arity, last, loc, callbackSite(fast ?? fnArg), fastT, present)
854
+ : someEveryHelper(lowerer, method, elem, fnRet, arity, loc, callbackSite(fast ?? fnArg), fastT, present);
545
855
  return {
546
856
  kind: "call",
547
857
  callee: helper,
548
- args: [receiver, fnArg],
858
+ args: [receiver, fnArg, ...(fast ? [fast] : [])],
549
859
  type: method === "findIndex" || method === "findLastIndex" ? F64 : BOOL,
550
860
  loc,
551
861
  };
@@ -555,7 +865,7 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
555
865
  // element inherits that earlier refinement. Otherwise only an inline,
556
866
  // inferred predicate proves a new narrowing; explicit assertions keep
557
867
  // the same refusal boundary as filter.
558
- const valueT = arrayValueType(lowerer, elem);
868
+ const valueT = callbackValueType(lowerer, elem, present);
559
869
  const checkerReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
560
870
  const checkerResult = lowerer.irTypeOf(call);
561
871
  const unchangedElement = checkerReceiver?.kind === "array" &&
@@ -581,10 +891,12 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
581
891
  lowerer.unsupported("SC1090", call, `'.${method}' result narrowing without a predicate over its element`);
582
892
  }
583
893
  retag = lowerer.narrowedRetagHelper(call, valueT.unionId, resultT.unionId, loc);
584
- if (retag === null)
894
+ const present = lowerer.stripUndefinedArm(resultT);
895
+ if (retag === null &&
896
+ !(present.kind === "object" && canAssertClassValue(lowerer, valueT, present)))
585
897
  lowerer.unsupported("SC1090", call, `'.${method}' narrowing to an incompatible result layout`);
586
898
  }
587
- const helper = findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag);
899
+ const helper = findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag, callbackSite(fnArg), present);
588
900
  return { kind: "call", callee: helper, args: [receiver, fnArg], type: resultT, loc };
589
901
  }
590
902
  /** ToBoolean of a predicate result inside a synthesized HOF helper — the
@@ -603,20 +915,26 @@ function predicateToBoolean(e) {
603
915
  * for (i = 0; i < n; i++) { v = a[i]; if (f(v)) return <v as result arm>; }
604
916
  * return <undefined arm>;
605
917
  */
606
- function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag) {
918
+ function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag, site = "", present = false) {
607
919
  const method = last ? "findLast" : "find";
608
- const key = `${method}:${typeKey(elem)}:${typeKey(resultT)}:${typeKey(fnRet)}:${arity}`;
920
+ const key = `${method}:${typeKey(elem)}:${typeKey(resultT)}:${typeKey(fnRet)}:${arity}${site}${present ? ":present" : ""}`;
609
921
  const existing = lowerer.arrHofHelpers.get(key);
610
922
  if (existing)
611
923
  return existing;
612
924
  const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
613
925
  lowerer.arrHofHelpers.set(key, name);
614
926
  const arrT = arrayOf(elem);
615
- const fnT = funcOf([arrayValueType(lowerer, elem), F64, arrT].slice(0, arity), fnRet);
616
- const valueT = arrayValueType(lowerer, elem);
927
+ const valueT = callbackValueType(lowerer, elem, present);
928
+ const fnT = funcOf([valueT, F64, arrT].slice(0, arity), fnRet);
617
929
  const v = varRef("v.0", valueT, loc);
930
+ const presentArm = lowerer.stripUndefinedArm(resultT);
931
+ // A successful inferred class predicate may select a descendant of a
932
+ // stored base arm. Keep the value read before the callback mutated the array.
933
+ const classView = retag === null && !lowerer.coercibleValue(valueT, resultT) && presentArm.kind === "object"
934
+ ? checkedClassAssertion(lowerer, v, presentArm, loc)
935
+ : null;
618
936
  const found = retag === null
619
- ? lowerer.coerceToExpected(v, resultT)
937
+ ? lowerer.coerceToExpected(classView ?? v, resultT)
620
938
  : { kind: "call", callee: retag, args: [v], type: resultT, loc };
621
939
  const miss = {
622
940
  kind: "unionWrap",
@@ -630,7 +948,7 @@ function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, r
630
948
  {
631
949
  kind: "varDecl",
632
950
  localId: "v.0",
633
- init: arrayValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, loc),
951
+ init: callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc),
634
952
  loc,
635
953
  },
636
954
  {
@@ -668,20 +986,20 @@ function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, r
668
986
  *
669
987
  * n = a.length; for (...) if (f(a[i], i, a)) return i; return -1;
670
988
  */
671
- function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
989
+ function findIndexHelper(lowerer, elem, fnRet, arity, last, loc, site = "", fastT = null, present = false) {
672
990
  const method = last ? "findLastIndex" : "findIndex";
673
- const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
991
+ const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
674
992
  const existing = lowerer.arrHofHelpers.get(key);
675
993
  if (existing)
676
994
  return existing;
677
995
  const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
678
996
  lowerer.arrHofHelpers.set(key, name);
679
997
  const arrT = arrayOf(elem);
680
- const fnT = funcOf([arrayValueType(lowerer, elem), F64, arrT].slice(0, arity), fnRet);
998
+ const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
681
999
  const visit = [
682
1000
  {
683
1001
  kind: "if",
684
- cond: predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, arrayValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, loc), loc)),
1002
+ cond: predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc)),
685
1003
  then: [{ kind: "return", value: varRef("i.0", F64, loc), loc }],
686
1004
  else_: null,
687
1005
  loc,
@@ -695,14 +1013,14 @@ function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
695
1013
  loop,
696
1014
  { kind: "return", value: { kind: "numLit", value: -1, type: F64, loc }, loc },
697
1015
  ];
698
- lowerer.liftedFns.push({
1016
+ lowerer.liftedFns.push(withFastCallback({
699
1017
  name,
700
1018
  params: arrayCallbackParams(arrT, fnT),
701
1019
  returnType: F64,
702
1020
  locals: [...arrayCallbackLocals(arrT, fnT)],
703
1021
  body,
704
1022
  loc,
705
- });
1023
+ }, fastT, elem));
706
1024
  return name;
707
1025
  }
708
1026
  /** The some/every loops — short-circuit early returns, JS-exact:
@@ -710,16 +1028,16 @@ function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
710
1028
  * some: n = a.length; for (...) if (f(a[i])) return true; return false;
711
1029
  * every: n = a.length; for (...) if (!f(a[i])) return false; return true;
712
1030
  */
713
- function someEveryHelper(lowerer, method, elem, fnRet, arity, loc) {
714
- const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
1031
+ function someEveryHelper(lowerer, method, elem, fnRet, arity, loc, site = "", fastT = null, present = false) {
1032
+ const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
715
1033
  const existing = lowerer.arrHofHelpers.get(key);
716
1034
  if (existing)
717
1035
  return existing;
718
1036
  const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
719
1037
  lowerer.arrHofHelpers.set(key, name);
720
1038
  const arrT = arrayOf(elem);
721
- const fnT = funcOf([arrayValueType(lowerer, elem), F64, arrT].slice(0, arity), fnRet);
722
- const callF = predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, arrayValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, loc), loc));
1039
+ const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
1040
+ const callF = predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc));
723
1041
  const body = [
724
1042
  arrayLengthDeclaration(arrT, loc),
725
1043
  countedFor(loc, varRef("n.0", F64, loc), () => [
@@ -743,14 +1061,14 @@ function someEveryHelper(lowerer, method, elem, fnRet, arity, loc) {
743
1061
  ]),
744
1062
  { kind: "return", value: boolLit(method !== "some", loc), loc },
745
1063
  ];
746
- lowerer.liftedFns.push({
1064
+ lowerer.liftedFns.push(withFastCallback({
747
1065
  name,
748
1066
  params: arrayCallbackParams(arrT, fnT),
749
1067
  returnType: BOOL,
750
1068
  locals: [...arrayCallbackLocals(arrT, fnT)],
751
1069
  body,
752
1070
  loc,
753
- });
1071
+ }, fastT, elem));
754
1072
  return name;
755
1073
  }
756
1074
  /** `a.flatMap(f)` — map plus a one-level flatten. A callback returning
@@ -766,7 +1084,8 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
766
1084
  const argNode = call.arguments[0];
767
1085
  if (!argNode)
768
1086
  lowerer.unsupported("SC1090", call, "this call form"); // tsc-guarded
769
- const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], arrT);
1087
+ const present = presentElements(lowerer, call, elem);
1088
+ const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [callbackValueType(lowerer, elem, present)], arrT);
770
1089
  const fnRet = fnArg.type.ret;
771
1090
  if (fnRet.kind === "dyn" ||
772
1091
  fnRet.kind === "jsval" ||
@@ -794,11 +1113,35 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
794
1113
  lowerer.badType(call, lowerer.typeOf(call));
795
1114
  requireProducedArrayElement(lowerer, call, "'.flatMap()'", fnRet);
796
1115
  const outElem = callbackArrayElement(lowerer, call, fnRet);
797
- const helper = arrayHofHelper(lowerer, "flatMap", elem, fnRet, arity, loc, outElem);
798
- return { kind: "call", callee: helper, args: [receiver, fnArg], type: arrayOf(outElem), loc };
1116
+ const fast = present
1117
+ ? null
1118
+ : lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, {
1119
+ fnArg,
1120
+ arity,
1121
+ });
1122
+ const helper = arrayHofHelper(lowerer, "flatMap", elem, fnRet, arity, loc, outElem, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
1123
+ return {
1124
+ kind: "call",
1125
+ callee: helper,
1126
+ args: [receiver, fnArg, ...(fast ? [fast] : [])],
1127
+ type: arrayOf(outElem),
1128
+ loc,
1129
+ };
799
1130
  }
800
- const helper = flatMapHelper(lowerer, elem, fnRet, arity, loc);
801
- return { kind: "call", callee: helper, args: [receiver, fnArg], type: fnRet, loc };
1131
+ const fast = present
1132
+ ? null
1133
+ : lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, {
1134
+ fnArg,
1135
+ arity,
1136
+ });
1137
+ const helper = flatMapHelper(lowerer, elem, fnRet, arity, loc, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
1138
+ return {
1139
+ kind: "call",
1140
+ callee: helper,
1141
+ args: [receiver, fnArg, ...(fast ? [fast] : [])],
1142
+ type: fnRet,
1143
+ loc,
1144
+ };
802
1145
  }
803
1146
  /** The flatMap loop (array-returning callback), from existing IR nodes:
804
1147
  *
@@ -809,8 +1152,8 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
809
1152
  * }
810
1153
  * return out;
811
1154
  */
812
- function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
813
- const key = `flatMap:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
1155
+ function flatMapHelper(lowerer, elem, fnRet, arity, loc, site = "", fastT = null, present = false) {
1156
+ const key = `flatMap:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
814
1157
  const existing = lowerer.arrHofHelpers.get(key);
815
1158
  if (existing)
816
1159
  return existing;
@@ -818,7 +1161,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
818
1161
  lowerer.arrHofHelpers.set(key, name);
819
1162
  const arrT = arrayOf(elem);
820
1163
  const inner = fnRet.elem;
821
- const fnT = funcOf([arrayValueType(lowerer, elem), F64, arrT].slice(0, arity), fnRet);
1164
+ const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
822
1165
  const innerLoop = {
823
1166
  kind: "for",
824
1167
  init: { kind: "varDecl", localId: "j.0", init: numLit(0, loc), loc },
@@ -885,7 +1228,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
885
1228
  {
886
1229
  kind: "varDecl",
887
1230
  localId: "r.0",
888
- init: callArrayCallback(arrT, fnT, fnRet, arity, arrayValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, loc), loc),
1231
+ init: callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc),
889
1232
  loc,
890
1233
  },
891
1234
  {
@@ -909,7 +1252,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
909
1252
  ]),
910
1253
  { kind: "return", value: varRef("out.0", fnRet, loc), loc },
911
1254
  ];
912
- lowerer.liftedFns.push({
1255
+ lowerer.liftedFns.push(withFastCallback({
913
1256
  name,
914
1257
  params: arrayCallbackParams(arrT, fnT),
915
1258
  returnType: fnRet,
@@ -923,7 +1266,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
923
1266
  ],
924
1267
  body,
925
1268
  loc,
926
- });
1269
+ }, fastT, elem));
927
1270
  return name;
928
1271
  }
929
1272
  /** `a.reduce(f)` / `a.reduce(f, init)` and reduceRight — both declared
@@ -944,10 +1287,15 @@ export function lowerArrayReduceCall(lowerer, call, access, method, elem) {
944
1287
  if (accT.kind === "void" || accT.kind === "func")
945
1288
  lowerer.badType(call, lowerer.typeOf(call));
946
1289
  const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [accT, arrayValueType(lowerer, elem)], arrT, false, accT);
947
- const helper = reduceHelper(lowerer, method, elem, accT, fnArg.type.ret, arity, hasInit, loc);
1290
+ const fast = lowerFastCallback(lowerer, argNode, [accT, arrayValueType(lowerer, elem)], 1, elem, arrT, { fnArg, arity }, false, accT);
1291
+ const helper = reduceHelper(lowerer, method, elem, accT, fnArg.type.ret, arity, hasInit, loc, callbackSite(fast ?? fnArg), fast?.type ?? null);
948
1292
  const args = [receiver, fnArg];
949
1293
  if (hasInit)
950
1294
  args.push(lowerer.lowerExprExpecting(call.arguments[1], accT));
1295
+ // The fast closure is created last; making a closure has no observable
1296
+ // effect, so the initial value still evaluates right after the callback.
1297
+ if (fast)
1298
+ args.push(fast);
951
1299
  return { kind: "call", callee: helper, args, type: accT, loc };
952
1300
  }
953
1301
  /** The reduce/reduceRight loops, from existing IR nodes:
@@ -960,8 +1308,8 @@ export function lowerArrayReduceCall(lowerer, call, access, method, elem) {
960
1308
  * reduce walks 0→n-1, reduceRight n-1→0; the seed without an initial
961
1309
  * value is a[0] / a[n-1] and the loop starts one past it. The empty-array
962
1310
  * TypeError message is Node's, byte for byte. */
963
- function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc) {
964
- const key = `${method}:${typeKey(elem)}:${typeKey(accT)}:${typeKey(fnRet)}:${arity}:${hasInit ? "init" : "seed"}`;
1311
+ function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc, site = "", fastT = null) {
1312
+ const key = `${method}:${typeKey(elem)}:${typeKey(accT)}:${typeKey(fnRet)}:${arity}:${hasInit ? "init" : "seed"}${site}${fastT ? ":split" : ""}`;
965
1313
  const existing = lowerer.arrHofHelpers.get(key);
966
1314
  if (existing)
967
1315
  return existing;
@@ -1101,7 +1449,7 @@ function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc) {
1101
1449
  loop,
1102
1450
  { kind: "return", value: varRef("acc.0", accT, loc), loc },
1103
1451
  ];
1104
- lowerer.liftedFns.push({ name, params, returnType: accT, locals, body, loc });
1452
+ lowerer.liftedFns.push(withFastCallback({ name, params, returnType: accT, locals, body, loc }, fastT, elem));
1105
1453
  return name;
1106
1454
  }
1107
1455
  /** `a.sort(cmp)` / `a.toSorted(cmp)`, desugared to an interned synthetic
@@ -1196,13 +1544,16 @@ export function lowerArraySortCall(lowerer, call, access, elem, arrT) {
1196
1544
  lowerer.badType(argNode, lowerer.typeOf(argNode));
1197
1545
  }
1198
1546
  const arity = fnArg.type.params.length;
1199
- const key = `${method}:${typeKey(elem)}:${arity}`;
1547
+ // The runtime sorts raw slots without per-move reference counting; this
1548
+ // beats the IR merge sort even when its comparator call becomes direct.
1549
+ const native = isSortValuesElement(elem, elem.kind === "union" ? lowerer.unions.get(elem.unionId)?.arms : undefined);
1550
+ const key = `${method}:${typeKey(elem)}:${arity}${native ? ":native" : ""}`;
1200
1551
  let helper = lowerer.arrHofHelpers.get(key);
1201
1552
  if (!helper) {
1202
1553
  helper = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
1203
1554
  lowerer.arrHofHelpers.set(key, helper);
1204
1555
  const undefinedTag = elem.kind === "union" ? lowerer.armTag(elem.unionId, UNDEFINED_T) : -1;
1205
- lowerer.liftedFns.push(buildArraySortFn(helper, elem, arity, copyFirst, undefinedTag >= 0 ? undefinedTag : null, loc));
1556
+ lowerer.liftedFns.push(buildArraySortFn(helper, elem, arity, copyFirst, undefinedTag >= 0 ? undefinedTag : null, loc, native));
1206
1557
  }
1207
1558
  return { kind: "call", callee: helper, args: [receiver, fnArg], type: arrT, loc };
1208
1559
  }