@geastack/compiler 1.0.15
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.
- package/LICENSE +202 -0
- package/README.md +149 -0
- package/dist/cli-analyze.d.ts +1 -0
- package/dist/cli-analyze.js +61 -0
- package/dist/cli-coverage.d.ts +1 -0
- package/dist/cli-coverage.js +329 -0
- package/dist/cli-emit.d.ts +10 -0
- package/dist/cli-emit.js +398 -0
- package/dist/cli-module-graph.d.ts +18 -0
- package/dist/cli-module-graph.js +123 -0
- package/dist/cli-package-source.d.ts +5 -0
- package/dist/cli-package-source.js +116 -0
- package/dist/cli-project.d.ts +2 -0
- package/dist/cli-project.js +60 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +199 -0
- package/dist/compiler.d.ts +228 -0
- package/dist/compiler.js +1029 -0
- package/dist/conversion/algebra.d.ts +218 -0
- package/dist/conversion/algebra.js +155 -0
- package/dist/conversion/build.d.ts +67 -0
- package/dist/conversion/build.js +1378 -0
- package/dist/conversion/derive.d.ts +37 -0
- package/dist/conversion/derive.js +260 -0
- package/dist/conversion/graph-validation.d.ts +8 -0
- package/dist/conversion/graph-validation.js +97 -0
- package/dist/conversion/native-callable-adapter.d.ts +13 -0
- package/dist/conversion/native-callable-adapter.js +53 -0
- package/dist/conversion/native-class-reference.d.ts +12 -0
- package/dist/conversion/native-class-reference.js +39 -0
- package/dist/conversion/native-payload-transport.d.ts +25 -0
- package/dist/conversion/native-payload-transport.js +33 -0
- package/dist/conversion/native-selection.d.ts +49 -0
- package/dist/conversion/native-selection.js +135 -0
- package/dist/conversion/native-sum.d.ts +42 -0
- package/dist/conversion/native-sum.js +115 -0
- package/dist/conversion/nodes.d.ts +55 -0
- package/dist/conversion/nodes.js +91 -0
- package/dist/conversion/operand-view.d.ts +14 -0
- package/dist/conversion/operand-view.js +20 -0
- package/dist/conversion/record-view.d.ts +157 -0
- package/dist/conversion/record-view.js +273 -0
- package/dist/conversion/registry.d.ts +217 -0
- package/dist/conversion/registry.js +1 -0
- package/dist/diagnostics/model.d.ts +76 -0
- package/dist/diagnostics/model.js +60 -0
- package/dist/diagnostics/sweep.d.ts +31 -0
- package/dist/diagnostics/sweep.js +112 -0
- package/dist/identity/ids.d.ts +179 -0
- package/dist/identity/ids.js +212 -0
- package/dist/ir/absent-class-arm.d.ts +48 -0
- package/dist/ir/absent-class-arm.js +157 -0
- package/dist/ir/borrow-effects.d.ts +23 -0
- package/dist/ir/borrow-effects.js +151 -0
- package/dist/ir/borrowed-call-arguments.d.ts +40 -0
- package/dist/ir/borrowed-call-arguments.js +117 -0
- package/dist/ir/build.d.ts +168 -0
- package/dist/ir/build.js +459 -0
- package/dist/ir/call-dispatch.d.ts +38 -0
- package/dist/ir/call-dispatch.js +502 -0
- package/dist/ir/call-entry.d.ts +142 -0
- package/dist/ir/call-entry.js +386 -0
- package/dist/ir/callable-class-flow.d.ts +27 -0
- package/dist/ir/callable-class-flow.js +1386 -0
- package/dist/ir/callable-field-slots.d.ts +22 -0
- package/dist/ir/callable-field-slots.js +166 -0
- package/dist/ir/callable-identity-demand.d.ts +52 -0
- package/dist/ir/callable-identity-demand.js +460 -0
- package/dist/ir/callable-member-candidates.d.ts +9 -0
- package/dist/ir/callable-member-candidates.js +39 -0
- package/dist/ir/callable-records.d.ts +21 -0
- package/dist/ir/callable-records.js +411 -0
- package/dist/ir/captures.d.ts +26 -0
- package/dist/ir/captures.js +335 -0
- package/dist/ir/certificate.d.ts +45 -0
- package/dist/ir/certificate.js +47 -0
- package/dist/ir/certify/carrier-keys.d.ts +73 -0
- package/dist/ir/certify/carrier-keys.js +221 -0
- package/dist/ir/certify/function-source.d.ts +4 -0
- package/dist/ir/certify/function-source.js +28 -0
- package/dist/ir/certify/has-property-key.d.ts +88 -0
- package/dist/ir/certify/has-property-key.js +116 -0
- package/dist/ir/certify/instanceof-key.d.ts +24 -0
- package/dist/ir/certify/instanceof-key.js +35 -0
- package/dist/ir/certify/property-access-keys.d.ts +172 -0
- package/dist/ir/certify/property-access-keys.js +291 -0
- package/dist/ir/certify/property-access.d.ts +3 -0
- package/dist/ir/certify/property-access.js +597 -0
- package/dist/ir/certify/runtime-helper.d.ts +3 -0
- package/dist/ir/certify/runtime-helper.js +326 -0
- package/dist/ir/certify/typeof-operand.d.ts +14 -0
- package/dist/ir/certify/typeof-operand.js +16 -0
- package/dist/ir/certify.d.ts +123 -0
- package/dist/ir/certify.js +481 -0
- package/dist/ir/class-evaluation.d.ts +26 -0
- package/dist/ir/class-evaluation.js +50 -0
- package/dist/ir/class-static-fields.d.ts +60 -0
- package/dist/ir/class-static-fields.js +108 -0
- package/dist/ir/construct-entry.d.ts +26 -0
- package/dist/ir/construct-entry.js +117 -0
- package/dist/ir/dead-values.d.ts +90 -0
- package/dist/ir/dead-values.js +184 -0
- package/dist/ir/deferral.d.ts +99 -0
- package/dist/ir/deferral.js +409 -0
- package/dist/ir/dense-loops.d.ts +230 -0
- package/dist/ir/dense-loops.js +697 -0
- package/dist/ir/dominance.d.ts +82 -0
- package/dist/ir/dominance.js +268 -0
- package/dist/ir/emission-representations.d.ts +71 -0
- package/dist/ir/emission-representations.js +350 -0
- package/dist/ir/facts.d.ts +218 -0
- package/dist/ir/facts.js +181 -0
- package/dist/ir/fixed-data-definition.d.ts +19 -0
- package/dist/ir/fixed-data-definition.js +49 -0
- package/dist/ir/generator-split.d.ts +38 -0
- package/dist/ir/generator-split.js +329 -0
- package/dist/ir/hoist.d.ts +55 -0
- package/dist/ir/hoist.js +375 -0
- package/dist/ir/instantiation.d.ts +61 -0
- package/dist/ir/instantiation.js +137 -0
- package/dist/ir/integer-storage.d.ts +170 -0
- package/dist/ir/integer-storage.js +822 -0
- package/dist/ir/integers.d.ts +161 -0
- package/dist/ir/integers.js +539 -0
- package/dist/ir/integrity-restrictions.d.ts +50 -0
- package/dist/ir/integrity-restrictions.js +118 -0
- package/dist/ir/local-iterators.d.ts +4 -0
- package/dist/ir/local-iterators.js +27 -0
- package/dist/ir/lower-allocation.d.ts +4 -0
- package/dist/ir/lower-allocation.js +325 -0
- package/dist/ir/lower-completion.d.ts +15 -0
- package/dist/ir/lower-completion.js +25 -0
- package/dist/ir/lower-destructuring.d.ts +5 -0
- package/dist/ir/lower-destructuring.js +693 -0
- package/dist/ir/lower-element.d.ts +29 -0
- package/dist/ir/lower-element.js +111 -0
- package/dist/ir/lower-exceptions.d.ts +47 -0
- package/dist/ir/lower-exceptions.js +92 -0
- package/dist/ir/lower-flow.d.ts +137 -0
- package/dist/ir/lower-flow.js +600 -0
- package/dist/ir/lower-graph.d.ts +218 -0
- package/dist/ir/lower-graph.js +687 -0
- package/dist/ir/lower-invocation.d.ts +4 -0
- package/dist/ir/lower-invocation.js +514 -0
- package/dist/ir/lower-narrow.d.ts +53 -0
- package/dist/ir/lower-narrow.js +320 -0
- package/dist/ir/lower-operands.d.ts +272 -0
- package/dist/ir/lower-operands.js +461 -0
- package/dist/ir/lower-property.d.ts +21 -0
- package/dist/ir/lower-property.js +132 -0
- package/dist/ir/lower-protocol.d.ts +11 -0
- package/dist/ir/lower-protocol.js +118 -0
- package/dist/ir/lower-short-circuit.d.ts +41 -0
- package/dist/ir/lower-short-circuit.js +63 -0
- package/dist/ir/lower.d.ts +82 -0
- package/dist/ir/lower.js +1346 -0
- package/dist/ir/model.d.ts +1474 -0
- package/dist/ir/model.js +6 -0
- package/dist/ir/native-absent-property.d.ts +3 -0
- package/dist/ir/native-absent-property.js +13 -0
- package/dist/ir/native-array-transport.d.ts +7 -0
- package/dist/ir/native-array-transport.js +46 -0
- package/dist/ir/native-callable-bind.d.ts +9 -0
- package/dist/ir/native-callable-bind.js +30 -0
- package/dist/ir/native-carrier-predicate.d.ts +34 -0
- package/dist/ir/native-carrier-predicate.js +49 -0
- package/dist/ir/native-class-accessor.d.ts +18 -0
- package/dist/ir/native-class-accessor.js +52 -0
- package/dist/ir/native-class-construction.d.ts +16 -0
- package/dist/ir/native-class-construction.js +71 -0
- package/dist/ir/native-class-initialization.d.ts +15 -0
- package/dist/ir/native-class-initialization.js +56 -0
- package/dist/ir/native-class-origins.d.ts +13 -0
- package/dist/ir/native-class-origins.js +237 -0
- package/dist/ir/native-dictionary-transport.d.ts +6 -0
- package/dist/ir/native-dictionary-transport.js +37 -0
- package/dist/ir/native-enumeration.d.ts +14 -0
- package/dist/ir/native-enumeration.js +26 -0
- package/dist/ir/native-equality.d.ts +10 -0
- package/dist/ir/native-equality.js +18 -0
- package/dist/ir/native-field-owner.d.ts +37 -0
- package/dist/ir/native-field-owner.js +183 -0
- package/dist/ir/native-fixed-layout.d.ts +41 -0
- package/dist/ir/native-fixed-layout.js +232 -0
- package/dist/ir/native-host-construction.d.ts +53 -0
- package/dist/ir/native-host-construction.js +62 -0
- package/dist/ir/native-key-query.d.ts +4 -0
- package/dist/ir/native-key-query.js +38 -0
- package/dist/ir/native-merge-transport.d.ts +25 -0
- package/dist/ir/native-merge-transport.js +71 -0
- package/dist/ir/native-record-index-transport.d.ts +11 -0
- package/dist/ir/native-record-index-transport.js +34 -0
- package/dist/ir/native-record-index.d.ts +12 -0
- package/dist/ir/native-record-index.js +27 -0
- package/dist/ir/native-reflect-field.d.ts +5 -0
- package/dist/ir/native-reflect-field.js +33 -0
- package/dist/ir/native-sequence-transport.d.ts +7 -0
- package/dist/ir/native-sequence-transport.js +53 -0
- package/dist/ir/numeric-intrinsics.d.ts +13 -0
- package/dist/ir/numeric-intrinsics.js +57 -0
- package/dist/ir/object-value-conversions.d.ts +20 -0
- package/dist/ir/object-value-conversions.js +50 -0
- package/dist/ir/physical-class-reflection.d.ts +9 -0
- package/dist/ir/physical-class-reflection.js +57 -0
- package/dist/ir/presence-proof.d.ts +42 -0
- package/dist/ir/presence-proof.js +490 -0
- package/dist/ir/program-facts.d.ts +106 -0
- package/dist/ir/program-facts.js +319 -0
- package/dist/ir/proven-branches.d.ts +16 -0
- package/dist/ir/proven-branches.js +219 -0
- package/dist/ir/queries.d.ts +41 -0
- package/dist/ir/queries.js +213 -0
- package/dist/ir/reflection-demand.d.ts +64 -0
- package/dist/ir/reflection-demand.js +1394 -0
- package/dist/ir/refusal.d.ts +43 -0
- package/dist/ir/refusal.js +28 -0
- package/dist/ir/shake.d.ts +37 -0
- package/dist/ir/shake.js +1078 -0
- package/dist/ir/static-callables.d.ts +11 -0
- package/dist/ir/static-callables.js +163 -0
- package/dist/ir/string-layout-reuse.d.ts +13 -0
- package/dist/ir/string-layout-reuse.js +39 -0
- package/dist/ir/string-length-reuse.d.ts +8 -0
- package/dist/ir/string-length-reuse.js +47 -0
- package/dist/ir/transfer.d.ts +78 -0
- package/dist/ir/transfer.js +270 -0
- package/dist/ir/type-query-results.d.ts +25 -0
- package/dist/ir/type-query-results.js +96 -0
- package/dist/ir/typed-property-access.d.ts +100 -0
- package/dist/ir/typed-property-access.js +161 -0
- package/dist/ir/verify.d.ts +19 -0
- package/dist/ir/verify.js +355 -0
- package/dist/plugins/apple/constructors.d.ts +112 -0
- package/dist/plugins/apple/constructors.js +217 -0
- package/dist/plugins/apple/host.d.ts +181 -0
- package/dist/plugins/apple/host.js +262 -0
- package/dist/plugins/apple/jsx.d.ts +2 -0
- package/dist/plugins/apple/jsx.js +293 -0
- package/dist/plugins/apple/members.d.ts +16 -0
- package/dist/plugins/apple/members.js +190 -0
- package/dist/plugins/apple/plugin.d.ts +2 -0
- package/dist/plugins/apple/plugin.js +156 -0
- package/dist/plugins/gea/component-classes.d.ts +25 -0
- package/dist/plugins/gea/component-classes.js +162 -0
- package/dist/plugins/gea/component-inline.d.ts +13 -0
- package/dist/plugins/gea/component-inline.js +532 -0
- package/dist/plugins/gea/constructors.d.ts +23 -0
- package/dist/plugins/gea/constructors.js +100 -0
- package/dist/plugins/gea/contract.d.ts +150 -0
- package/dist/plugins/gea/contract.js +195 -0
- package/dist/plugins/gea/element-ref.d.ts +31 -0
- package/dist/plugins/gea/element-ref.js +45 -0
- package/dist/plugins/gea/host.d.ts +520 -0
- package/dist/plugins/gea/host.js +762 -0
- package/dist/plugins/gea/lower.d.ts +6 -0
- package/dist/plugins/gea/lower.js +195 -0
- package/dist/plugins/gea/members.d.ts +22 -0
- package/dist/plugins/gea/members.js +221 -0
- package/dist/plugins/gea/plugin.d.ts +22 -0
- package/dist/plugins/gea/plugin.js +307 -0
- package/dist/plugins/gea/prelude.d.ts +78 -0
- package/dist/plugins/gea/prelude.js +153 -0
- package/dist/plugins/gea/producer.d.ts +5 -0
- package/dist/plugins/gea/producer.js +52 -0
- package/dist/plugins/gea/reactive-slots.d.ts +49 -0
- package/dist/plugins/gea/reactive-slots.js +578 -0
- package/dist/plugins/gea/render-bridge.d.ts +6 -0
- package/dist/plugins/gea/render-bridge.js +281 -0
- package/dist/plugins/gea/slots.d.ts +15 -0
- package/dist/plugins/gea/slots.js +36 -0
- package/dist/plugins/gea/template-analysis.d.ts +151 -0
- package/dist/plugins/gea/template-analysis.js +346 -0
- package/dist/plugins/gea/user-agent-styles.d.ts +9 -0
- package/dist/plugins/gea/user-agent-styles.js +94 -0
- package/dist/plugins/installed.d.ts +19 -0
- package/dist/plugins/installed.js +21 -0
- package/dist/plugins/load.d.ts +7 -0
- package/dist/plugins/load.js +207 -0
- package/dist/plugins/model.d.ts +735 -0
- package/dist/plugins/model.js +47 -0
- package/dist/plugins/webgl/host.d.ts +77 -0
- package/dist/plugins/webgl/host.js +162 -0
- package/dist/plugins/webgl/plugin.d.ts +40 -0
- package/dist/plugins/webgl/plugin.js +99 -0
- package/dist/preflight/obligations.d.ts +206 -0
- package/dist/preflight/obligations.js +36 -0
- package/dist/preflight/report.d.ts +20 -0
- package/dist/preflight/report.js +61 -0
- package/dist/preflight/run.d.ts +39 -0
- package/dist/preflight/run.js +403 -0
- package/dist/project-preparation.d.ts +33 -0
- package/dist/project-preparation.js +314 -0
- package/dist/projection/abi.d.ts +82 -0
- package/dist/projection/abi.js +349 -0
- package/dist/projection/apply-arguments.d.ts +12 -0
- package/dist/projection/apply-arguments.js +20 -0
- package/dist/projection/bindings.d.ts +250 -0
- package/dist/projection/bindings.js +340 -0
- package/dist/projection/callee.d.ts +196 -0
- package/dist/projection/callee.js +444 -0
- package/dist/projection/class-property-presence.d.ts +28 -0
- package/dist/projection/class-property-presence.js +58 -0
- package/dist/projection/class-prototype.d.ts +5 -0
- package/dist/projection/class-prototype.js +23 -0
- package/dist/projection/class-storage.d.ts +26 -0
- package/dist/projection/class-storage.js +236 -0
- package/dist/projection/classes.d.ts +283 -0
- package/dist/projection/classes.js +944 -0
- package/dist/projection/coercions.d.ts +20 -0
- package/dist/projection/coercions.js +33 -0
- package/dist/projection/dispatch.d.ts +167 -0
- package/dist/projection/dispatch.js +379 -0
- package/dist/projection/fields.d.ts +123 -0
- package/dist/projection/fields.js +383 -0
- package/dist/projection/instance-test.d.ts +78 -0
- package/dist/projection/instance-test.js +156 -0
- package/dist/projection/slots.d.ts +146 -0
- package/dist/projection/slots.js +663 -0
- package/dist/projection/synthesized-abi.d.ts +61 -0
- package/dist/projection/synthesized-abi.js +94 -0
- package/dist/representation/array-index.d.ts +14 -0
- package/dist/representation/array-index.js +17 -0
- package/dist/representation/callable-object.d.ts +3 -0
- package/dist/representation/callable-object.js +6 -0
- package/dist/representation/collections.d.ts +84 -0
- package/dist/representation/collections.js +139 -0
- package/dist/representation/derive.d.ts +159 -0
- package/dist/representation/derive.js +2546 -0
- package/dist/representation/difference.d.ts +30 -0
- package/dist/representation/difference.js +240 -0
- package/dist/representation/field-descriptor-policy.d.ts +19 -0
- package/dist/representation/field-descriptor-policy.js +39 -0
- package/dist/representation/function-constructor.d.ts +13 -0
- package/dist/representation/function-constructor.js +9 -0
- package/dist/representation/host-abi.d.ts +32 -0
- package/dist/representation/host-abi.js +97 -0
- package/dist/representation/host-templates.d.ts +67 -0
- package/dist/representation/host-templates.js +94 -0
- package/dist/representation/intersection.d.ts +84 -0
- package/dist/representation/intersection.js +149 -0
- package/dist/representation/literal-destination.d.ts +43 -0
- package/dist/representation/literal-destination.js +133 -0
- package/dist/representation/merge.d.ts +18 -0
- package/dist/representation/merge.js +83 -0
- package/dist/representation/model.d.ts +1160 -0
- package/dist/representation/model.js +1019 -0
- package/dist/representation/numeric-index.d.ts +13 -0
- package/dist/representation/numeric-index.js +29 -0
- package/dist/representation/object-shape.d.ts +109 -0
- package/dist/representation/object-shape.js +123 -0
- package/dist/representation/optional.d.ts +12 -0
- package/dist/representation/optional.js +87 -0
- package/dist/representation/plan.d.ts +60 -0
- package/dist/representation/plan.js +78 -0
- package/dist/representation/policies.d.ts +589 -0
- package/dist/representation/policies.js +107 -0
- package/dist/representation/primitive-domain.d.ts +1 -0
- package/dist/representation/primitive-domain.js +1 -0
- package/dist/representation/primitives.d.ts +44 -0
- package/dist/representation/primitives.js +78 -0
- package/dist/representation/publish.d.ts +49 -0
- package/dist/representation/publish.js +648 -0
- package/dist/representation/record-fields.d.ts +96 -0
- package/dist/representation/record-fields.js +116 -0
- package/dist/representation/template-object.d.ts +11 -0
- package/dist/representation/template-object.js +26 -0
- package/dist/representation/union.d.ts +30 -0
- package/dist/representation/union.js +324 -0
- package/dist/representation/value-records.d.ts +3 -0
- package/dist/representation/value-records.js +307 -0
- package/dist/representation/verify.d.ts +17 -0
- package/dist/representation/verify.js +221 -0
- package/dist/semantics/alias-this-field-declaration-transform.d.ts +4 -0
- package/dist/semantics/alias-this-field-declaration-transform.js +207 -0
- package/dist/semantics/ambient-type-realization-transform.d.ts +62 -0
- package/dist/semantics/ambient-type-realization-transform.js +168 -0
- package/dist/semantics/ambient.d.ts +24 -0
- package/dist/semantics/ambient.js +119 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.d.ts +4 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.js +341 -0
- package/dist/semantics/callable-origins.d.ts +46 -0
- package/dist/semantics/callable-origins.js +354 -0
- package/dist/semantics/class-alias.d.ts +7 -0
- package/dist/semantics/class-alias.js +37 -0
- package/dist/semantics/class-heritage.d.ts +34 -0
- package/dist/semantics/class-heritage.js +104 -0
- package/dist/semantics/commonjs-wrapper.d.ts +69 -0
- package/dist/semantics/commonjs-wrapper.js +231 -0
- package/dist/semantics/constructor-slot-subclasses.d.ts +28 -0
- package/dist/semantics/constructor-slot-subclasses.js +112 -0
- package/dist/semantics/declaration-overlay-transform.d.ts +35 -0
- package/dist/semantics/declaration-overlay-transform.js +2157 -0
- package/dist/semantics/define-property-source-transform.d.ts +4 -0
- package/dist/semantics/define-property-source-transform.js +437 -0
- package/dist/semantics/diagnostic-source-preparation.d.ts +24 -0
- package/dist/semantics/diagnostic-source-preparation.js +82 -0
- package/dist/semantics/documentation-ranges.d.ts +22 -0
- package/dist/semantics/documentation-ranges.js +36 -0
- package/dist/semantics/dynamic-fallback.d.ts +86 -0
- package/dist/semantics/dynamic-fallback.js +249 -0
- package/dist/semantics/frontend-timing.d.ts +6 -0
- package/dist/semantics/frontend-timing.js +35 -0
- package/dist/semantics/frontend.d.ts +504 -0
- package/dist/semantics/frontend.js +1157 -0
- package/dist/semantics/host-declaration-provenance.d.ts +11 -0
- package/dist/semantics/host-declaration-provenance.js +18 -0
- package/dist/semantics/host-methods.d.ts +24 -0
- package/dist/semantics/host-methods.js +74 -0
- package/dist/semantics/host-protocols.d.ts +429 -0
- package/dist/semantics/host-protocols.js +1501 -0
- package/dist/semantics/inherited-accessor.d.ts +7 -0
- package/dist/semantics/inherited-accessor.js +48 -0
- package/dist/semantics/interface-families.d.ts +70 -0
- package/dist/semantics/interface-families.js +180 -0
- package/dist/semantics/interface-implementors.d.ts +53 -0
- package/dist/semantics/interface-implementors.js +87 -0
- package/dist/semantics/jsdoc-namepath-transform.d.ts +4 -0
- package/dist/semantics/jsdoc-namepath-transform.js +85 -0
- package/dist/semantics/model/coverage.d.ts +68 -0
- package/dist/semantics/model/coverage.js +73 -0
- package/dist/semantics/model/edges.d.ts +103 -0
- package/dist/semantics/model/edges.js +20 -0
- package/dist/semantics/model/graph.d.ts +55 -0
- package/dist/semantics/model/graph.js +129 -0
- package/dist/semantics/model/operands.d.ts +159 -0
- package/dist/semantics/model/operands.js +26 -0
- package/dist/semantics/model/operations.d.ts +496 -0
- package/dist/semantics/model/operations.js +2 -0
- package/dist/semantics/model/primitive-domain.d.ts +26 -0
- package/dist/semantics/model/primitive-domain.js +38 -0
- package/dist/semantics/model/selected-signature.d.ts +261 -0
- package/dist/semantics/model/selected-signature.js +55 -0
- package/dist/semantics/model/structural-type-table.d.ts +93 -0
- package/dist/semantics/model/structural-type-table.js +237 -0
- package/dist/semantics/model/structural-types.d.ts +367 -0
- package/dist/semantics/model/structural-types.js +200 -0
- package/dist/semantics/module-resolution.d.ts +23 -0
- package/dist/semantics/module-resolution.js +227 -0
- package/dist/semantics/new-callee-class-tag-source-transform.d.ts +4 -0
- package/dist/semantics/new-callee-class-tag-source-transform.js +64 -0
- package/dist/semantics/node-project.d.ts +13 -0
- package/dist/semantics/node-project.js +107 -0
- package/dist/semantics/node-source-hooks.d.ts +1 -0
- package/dist/semantics/node-source-hooks.js +63 -0
- package/dist/semantics/normalize/absent-globals.d.ts +143 -0
- package/dist/semantics/normalize/absent-globals.js +191 -0
- package/dist/semantics/normalize/arguments-objects.d.ts +43 -0
- package/dist/semantics/normalize/arguments-objects.js +60 -0
- package/dist/semantics/normalize/asserted-arm-absence.d.ts +28 -0
- package/dist/semantics/normalize/asserted-arm-absence.js +61 -0
- package/dist/semantics/normalize/assignment-patterns.d.ts +70 -0
- package/dist/semantics/normalize/assignment-patterns.js +147 -0
- package/dist/semantics/normalize/bag-absence.d.ts +8 -0
- package/dist/semantics/normalize/bag-absence.js +42 -0
- package/dist/semantics/normalize/binding-fixpoint.d.ts +36 -0
- package/dist/semantics/normalize/binding-fixpoint.js +140 -0
- package/dist/semantics/normalize/callback-parameter-contracts.d.ts +16 -0
- package/dist/semantics/normalize/callback-parameter-contracts.js +91 -0
- package/dist/semantics/normalize/cells/agreement.d.ts +46 -0
- package/dist/semantics/normalize/cells/agreement.js +34 -0
- package/dist/semantics/normalize/cells/candidates.d.ts +17 -0
- package/dist/semantics/normalize/cells/candidates.js +35 -0
- package/dist/semantics/normalize/cells/facts.d.ts +19 -0
- package/dist/semantics/normalize/cells/facts.js +90 -0
- package/dist/semantics/normalize/cells/index.d.ts +10 -0
- package/dist/semantics/normalize/cells/index.js +6 -0
- package/dist/semantics/normalize/cells/model.d.ts +98 -0
- package/dist/semantics/normalize/cells/model.js +2 -0
- package/dist/semantics/normalize/cells/policies/bag.d.ts +44 -0
- package/dist/semantics/normalize/cells/policies/bag.js +114 -0
- package/dist/semantics/normalize/cells/policies/collection.d.ts +42 -0
- package/dist/semantics/normalize/cells/policies/collection.js +218 -0
- package/dist/semantics/normalize/cells/policies/field.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/field.js +40 -0
- package/dist/semantics/normalize/cells/policies/index.d.ts +49 -0
- package/dist/semantics/normalize/cells/policies/index.js +58 -0
- package/dist/semantics/normalize/cells/policies/local.d.ts +18 -0
- package/dist/semantics/normalize/cells/policies/local.js +37 -0
- package/dist/semantics/normalize/cells/policies/parameter.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/parameter.js +39 -0
- package/dist/semantics/normalize/cells/policies/return.d.ts +26 -0
- package/dist/semantics/normalize/cells/policies/return.js +45 -0
- package/dist/semantics/normalize/cells/policies/shared.d.ts +33 -0
- package/dist/semantics/normalize/cells/policies/shared.js +45 -0
- package/dist/semantics/normalize/cells/policy.d.ts +72 -0
- package/dist/semantics/normalize/cells/policy.js +18 -0
- package/dist/semantics/normalize/cells/registry.d.ts +14 -0
- package/dist/semantics/normalize/cells/registry.js +17 -0
- package/dist/semantics/normalize/census-refusal.d.ts +62 -0
- package/dist/semantics/normalize/census-refusal.js +27 -0
- package/dist/semantics/normalize/census.d.ts +109 -0
- package/dist/semantics/normalize/census.js +667 -0
- package/dist/semantics/normalize/collection-bindings.d.ts +278 -0
- package/dist/semantics/normalize/collection-bindings.js +677 -0
- package/dist/semantics/normalize/commonjs-module-record.d.ts +21 -0
- package/dist/semantics/normalize/commonjs-module-record.js +289 -0
- package/dist/semantics/normalize/commonjs-require.d.ts +13 -0
- package/dist/semantics/normalize/commonjs-require.js +1527 -0
- package/dist/semantics/normalize/contribution.d.ts +63 -0
- package/dist/semantics/normalize/contribution.js +172 -0
- package/dist/semantics/normalize/dead-typeof-guards.d.ts +64 -0
- package/dist/semantics/normalize/dead-typeof-guards.js +152 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.d.ts +57 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.js +109 -0
- package/dist/semantics/normalize/derived-expression-type.d.ts +1070 -0
- package/dist/semantics/normalize/derived-expression-type.js +3463 -0
- package/dist/semantics/normalize/evaluation-order.d.ts +16 -0
- package/dist/semantics/normalize/evaluation-order.js +37 -0
- package/dist/semantics/normalize/field-bindings.d.ts +167 -0
- package/dist/semantics/normalize/field-bindings.js +1125 -0
- package/dist/semantics/normalize/flow/array-element-continuation.d.ts +27 -0
- package/dist/semantics/normalize/flow/array-element-continuation.js +1452 -0
- package/dist/semantics/normalize/flow/callable-array-origins.d.ts +42 -0
- package/dist/semantics/normalize/flow/callable-array-origins.js +318 -0
- package/dist/semantics/normalize/flow/callable-completions.d.ts +45 -0
- package/dist/semantics/normalize/flow/callable-completions.js +82 -0
- package/dist/semantics/normalize/flow/callable-reach.d.ts +237 -0
- package/dist/semantics/normalize/flow/callable-reach.js +7174 -0
- package/dist/semantics/normalize/flow/class-family-member-read.d.ts +16 -0
- package/dist/semantics/normalize/flow/class-family-member-read.js +992 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.d.ts +21 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.js +192 -0
- package/dist/semantics/normalize/flow/component-solver.d.ts +199 -0
- package/dist/semantics/normalize/flow/component-solver.js +587 -0
- package/dist/semantics/normalize/flow/computed-key-set.d.ts +84 -0
- package/dist/semantics/normalize/flow/computed-key-set.js +660 -0
- package/dist/semantics/normalize/flow/export-importers.d.ts +24 -0
- package/dist/semantics/normalize/flow/export-importers.js +269 -0
- package/dist/semantics/normalize/flow/host-text-sink.d.ts +25 -0
- package/dist/semantics/normalize/flow/host-text-sink.js +87 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.d.ts +84 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.js +180 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.d.ts +35 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.js +140 -0
- package/dist/semantics/normalize/flow/invocation-facts.d.ts +98 -0
- package/dist/semantics/normalize/flow/invocation-facts.js +257 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.d.ts +122 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.js +835 -0
- package/dist/semantics/normalize/flow/model.d.ts +357 -0
- package/dist/semantics/normalize/flow/model.js +177 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.d.ts +24 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.js +252 -0
- package/dist/semantics/normalize/flow/node-path-token.d.ts +3 -0
- package/dist/semantics/normalize/flow/node-path-token.js +53 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.d.ts +11 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.js +42 -0
- package/dist/semantics/normalize/flow/origin-authority.d.ts +56 -0
- package/dist/semantics/normalize/flow/origin-authority.js +2 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.d.ts +35 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.js +191 -0
- package/dist/semantics/normalize/flow/parameter-values.d.ts +27 -0
- package/dist/semantics/normalize/flow/parameter-values.js +251 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.d.ts +66 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.js +162 -0
- package/dist/semantics/normalize/flow/record-alias-closure.d.ts +27 -0
- package/dist/semantics/normalize/flow/record-alias-closure.js +298 -0
- package/dist/semantics/normalize/flow/seeded-origins.d.ts +43 -0
- package/dist/semantics/normalize/flow/seeded-origins.js +54 -0
- package/dist/semantics/normalize/flow/source-class-data.d.ts +132 -0
- package/dist/semantics/normalize/flow/source-class-data.js +838 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.d.ts +13 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.js +37 -0
- package/dist/semantics/normalize/flow/source-class-static-data.d.ts +16 -0
- package/dist/semantics/normalize/flow/source-class-static-data.js +47 -0
- package/dist/semantics/normalize/flow/source-construction-frames.d.ts +12 -0
- package/dist/semantics/normalize/flow/source-construction-frames.js +118 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.d.ts +34 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.js +78 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.d.ts +37 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.js +95 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.d.ts +23 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.js +81 -0
- package/dist/semantics/normalize/flow/source-record-data.d.ts +29 -0
- package/dist/semantics/normalize/flow/source-record-data.js +626 -0
- package/dist/semantics/normalize/flow/source-value-session.d.ts +77 -0
- package/dist/semantics/normalize/flow/source-value-session.js +3089 -0
- package/dist/semantics/normalize/flow/targets.d.ts +118 -0
- package/dist/semantics/normalize/flow/targets.js +405 -0
- package/dist/semantics/normalize/flow/value-flow.d.ts +36 -0
- package/dist/semantics/normalize/flow/value-flow.js +823 -0
- package/dist/semantics/normalize/flow/value-provenance.d.ts +31 -0
- package/dist/semantics/normalize/flow/value-provenance.js +112 -0
- package/dist/semantics/normalize/gating.d.ts +51 -0
- package/dist/semantics/normalize/gating.js +560 -0
- package/dist/semantics/normalize/generic-function-choice.d.ts +31 -0
- package/dist/semantics/normalize/generic-function-choice.js +115 -0
- package/dist/semantics/normalize/global-host-mutations.d.ts +51 -0
- package/dist/semantics/normalize/global-host-mutations.js +5989 -0
- package/dist/semantics/normalize/host-effect-contracts.d.ts +77 -0
- package/dist/semantics/normalize/host-effect-contracts.js +143 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.d.ts +38 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.js +26 -0
- package/dist/semantics/normalize/host-mutation-key-reader.d.ts +66 -0
- package/dist/semantics/normalize/host-mutation-key-reader.js +192 -0
- package/dist/semantics/normalize/host-mutation-keys.d.ts +114 -0
- package/dist/semantics/normalize/host-mutation-keys.js +183 -0
- package/dist/semantics/normalize/identities.d.ts +172 -0
- package/dist/semantics/normalize/identities.js +426 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.d.ts +97 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.js +197 -0
- package/dist/semantics/normalize/implicit-arguments.d.ts +11 -0
- package/dist/semantics/normalize/implicit-arguments.js +39 -0
- package/dist/semantics/normalize/instantiation.d.ts +73 -0
- package/dist/semantics/normalize/instantiation.js +399 -0
- package/dist/semantics/normalize/intrinsic-property-call.d.ts +18 -0
- package/dist/semantics/normalize/intrinsic-property-call.js +69 -0
- package/dist/semantics/normalize/intrinsic-prototype.d.ts +41 -0
- package/dist/semantics/normalize/intrinsic-prototype.js +87 -0
- package/dist/semantics/normalize/intrinsic-static-member.d.ts +14 -0
- package/dist/semantics/normalize/intrinsic-static-member.js +23 -0
- package/dist/semantics/normalize/jsdoc-type-names.d.ts +32 -0
- package/dist/semantics/normalize/jsdoc-type-names.js +512 -0
- package/dist/semantics/normalize/keyof.d.ts +32 -0
- package/dist/semantics/normalize/keyof.js +110 -0
- package/dist/semantics/normalize/local-bindings.d.ts +176 -0
- package/dist/semantics/normalize/local-bindings.js +1826 -0
- package/dist/semantics/normalize/logical-result-type.d.ts +16 -0
- package/dist/semantics/normalize/logical-result-type.js +102 -0
- package/dist/semantics/normalize/namespace-paths.d.ts +57 -0
- package/dist/semantics/normalize/namespace-paths.js +108 -0
- package/dist/semantics/normalize/normalize.d.ts +57 -0
- package/dist/semantics/normalize/normalize.js +68 -0
- package/dist/semantics/normalize/object-bag-bindings.d.ts +305 -0
- package/dist/semantics/normalize/object-bag-bindings.js +1290 -0
- package/dist/semantics/normalize/omitted-stated-parameter.d.ts +53 -0
- package/dist/semantics/normalize/omitted-stated-parameter.js +59 -0
- package/dist/semantics/normalize/open-type-form.d.ts +10 -0
- package/dist/semantics/normalize/open-type-form.js +32 -0
- package/dist/semantics/normalize/parameter-bindings.d.ts +361 -0
- package/dist/semantics/normalize/parameter-bindings.js +3339 -0
- package/dist/semantics/normalize/parameter-slot.d.ts +264 -0
- package/dist/semantics/normalize/parameter-slot.js +491 -0
- package/dist/semantics/normalize/physical-overload-result.d.ts +77 -0
- package/dist/semantics/normalize/physical-overload-result.js +99 -0
- package/dist/semantics/normalize/primitive-property-absence.d.ts +12 -0
- package/dist/semantics/normalize/primitive-property-absence.js +60 -0
- package/dist/semantics/normalize/producer-context.d.ts +376 -0
- package/dist/semantics/normalize/producer-context.js +1 -0
- package/dist/semantics/normalize/producers/allocations.d.ts +3 -0
- package/dist/semantics/normalize/producers/allocations.js +863 -0
- package/dist/semantics/normalize/producers/binding-kind.d.ts +37 -0
- package/dist/semantics/normalize/producers/binding-kind.js +36 -0
- package/dist/semantics/normalize/producers/bindings.d.ts +85 -0
- package/dist/semantics/normalize/producers/bindings.js +710 -0
- package/dist/semantics/normalize/producers/boundary.d.ts +34 -0
- package/dist/semantics/normalize/producers/boundary.js +123 -0
- package/dist/semantics/normalize/producers/class-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/class-lifecycle.js +902 -0
- package/dist/semantics/normalize/producers/computations.d.ts +3 -0
- package/dist/semantics/normalize/producers/computations.js +613 -0
- package/dist/semantics/normalize/producers/control-loops.d.ts +30 -0
- package/dist/semantics/normalize/producers/control-loops.js +91 -0
- package/dist/semantics/normalize/producers/control.d.ts +30 -0
- package/dist/semantics/normalize/producers/control.js +923 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.js +390 -0
- package/dist/semantics/normalize/producers/destructuring.d.ts +45 -0
- package/dist/semantics/normalize/producers/destructuring.js +1180 -0
- package/dist/semantics/normalize/producers/dynamic-language.d.ts +3 -0
- package/dist/semantics/normalize/producers/dynamic-language.js +70 -0
- package/dist/semantics/normalize/producers/erasure.d.ts +51 -0
- package/dist/semantics/normalize/producers/erasure.js +90 -0
- package/dist/semantics/normalize/producers/installed.d.ts +3 -0
- package/dist/semantics/normalize/producers/installed.js +55 -0
- package/dist/semantics/normalize/producers/invocations.d.ts +35 -0
- package/dist/semantics/normalize/producers/invocations.js +1796 -0
- package/dist/semantics/normalize/producers/iteration-yield.d.ts +59 -0
- package/dist/semantics/normalize/producers/iteration-yield.js +235 -0
- package/dist/semantics/normalize/producers/jsx.d.ts +3 -0
- package/dist/semantics/normalize/producers/jsx.js +360 -0
- package/dist/semantics/normalize/producers/mint.d.ts +39 -0
- package/dist/semantics/normalize/producers/mint.js +44 -0
- package/dist/semantics/normalize/producers/nullish.d.ts +16 -0
- package/dist/semantics/normalize/producers/nullish.js +27 -0
- package/dist/semantics/normalize/producers/object-assignment.d.ts +8 -0
- package/dist/semantics/normalize/producers/object-assignment.js +204 -0
- package/dist/semantics/normalize/producers/object-tag.d.ts +9 -0
- package/dist/semantics/normalize/producers/object-tag.js +119 -0
- package/dist/semantics/normalize/producers/optional-chain.d.ts +44 -0
- package/dist/semantics/normalize/producers/optional-chain.js +75 -0
- package/dist/semantics/normalize/producers/properties.d.ts +21 -0
- package/dist/semantics/normalize/producers/properties.js +1053 -0
- package/dist/semantics/normalize/producers/protocol.d.ts +67 -0
- package/dist/semantics/normalize/producers/protocol.js +695 -0
- package/dist/semantics/normalize/producers/references.d.ts +53 -0
- package/dist/semantics/normalize/producers/references.js +1027 -0
- package/dist/semantics/normalize/producers/shared.d.ts +561 -0
- package/dist/semantics/normalize/producers/shared.js +1683 -0
- package/dist/semantics/normalize/producers/spread-arguments.d.ts +72 -0
- package/dist/semantics/normalize/producers/spread-arguments.js +375 -0
- package/dist/semantics/normalize/producers/tagged-template.d.ts +5 -0
- package/dist/semantics/normalize/producers/tagged-template.js +307 -0
- package/dist/semantics/normalize/producers/tuple-spread.d.ts +189 -0
- package/dist/semantics/normalize/producers/tuple-spread.js +279 -0
- package/dist/semantics/normalize/property-key-domain.d.ts +36 -0
- package/dist/semantics/normalize/property-key-domain.js +150 -0
- package/dist/semantics/normalize/reachability.d.ts +189 -0
- package/dist/semantics/normalize/reachability.js +1057 -0
- package/dist/semantics/normalize/reassigned-bindings.d.ts +13 -0
- package/dist/semantics/normalize/reassigned-bindings.js +41 -0
- package/dist/semantics/normalize/record-storage-families.d.ts +11 -0
- package/dist/semantics/normalize/record-storage-families.js +109 -0
- package/dist/semantics/normalize/return-bindings.d.ts +260 -0
- package/dist/semantics/normalize/return-bindings.js +1311 -0
- package/dist/semantics/normalize/return-paths.d.ts +2 -0
- package/dist/semantics/normalize/return-paths.js +28 -0
- package/dist/semantics/normalize/script-global-redefinition.d.ts +44 -0
- package/dist/semantics/normalize/script-global-redefinition.js +75 -0
- package/dist/semantics/normalize/specialization.d.ts +201 -0
- package/dist/semantics/normalize/specialization.js +1824 -0
- package/dist/semantics/normalize/structural-array-element.d.ts +176 -0
- package/dist/semantics/normalize/structural-array-element.js +700 -0
- package/dist/semantics/normalize/structural-array-read.d.ts +13 -0
- package/dist/semantics/normalize/structural-array-read.js +124 -0
- package/dist/semantics/normalize/structural-callable.d.ts +12 -0
- package/dist/semantics/normalize/structural-callable.js +82 -0
- package/dist/semantics/normalize/structural-creation-order.d.ts +32 -0
- package/dist/semantics/normalize/structural-creation-order.js +111 -0
- package/dist/semantics/normalize/structural-declarations.d.ts +395 -0
- package/dist/semantics/normalize/structural-declarations.js +968 -0
- package/dist/semantics/normalize/structural-declared-body.d.ts +25 -0
- package/dist/semantics/normalize/structural-declared-body.js +147 -0
- package/dist/semantics/normalize/structural-generics.d.ts +56 -0
- package/dist/semantics/normalize/structural-generics.js +120 -0
- package/dist/semantics/normalize/structural-indexed-access.d.ts +11 -0
- package/dist/semantics/normalize/structural-indexed-access.js +126 -0
- package/dist/semantics/normalize/structural-instantiated-member.d.ts +64 -0
- package/dist/semantics/normalize/structural-instantiated-member.js +407 -0
- package/dist/semantics/normalize/structural-joins.d.ts +44 -0
- package/dist/semantics/normalize/structural-joins.js +143 -0
- package/dist/semantics/normalize/structural-layout-relevance.d.ts +29 -0
- package/dist/semantics/normalize/structural-layout-relevance.js +391 -0
- package/dist/semantics/normalize/structural-layout-type.d.ts +11 -0
- package/dist/semantics/normalize/structural-layout-type.js +1468 -0
- package/dist/semantics/normalize/structural-leaves.d.ts +49 -0
- package/dist/semantics/normalize/structural-leaves.js +125 -0
- package/dist/semantics/normalize/structural-local-union.d.ts +13 -0
- package/dist/semantics/normalize/structural-local-union.js +133 -0
- package/dist/semantics/normalize/structural-members.d.ts +26 -0
- package/dist/semantics/normalize/structural-members.js +84 -0
- package/dist/semantics/normalize/structural-mutable-method.d.ts +15 -0
- package/dist/semantics/normalize/structural-mutable-method.js +109 -0
- package/dist/semantics/normalize/structural-parts.d.ts +131 -0
- package/dist/semantics/normalize/structural-parts.js +737 -0
- package/dist/semantics/normalize/structural-receiver.d.ts +66 -0
- package/dist/semantics/normalize/structural-receiver.js +551 -0
- package/dist/semantics/normalize/structural-rules.d.ts +112 -0
- package/dist/semantics/normalize/structural-rules.js +93 -0
- package/dist/semantics/normalize/structural-self-reference.d.ts +150 -0
- package/dist/semantics/normalize/structural-self-reference.js +494 -0
- package/dist/semantics/normalize/structural.d.ts +202 -0
- package/dist/semantics/normalize/structural.js +4218 -0
- package/dist/semantics/normalize/unreduced-type-form.d.ts +41 -0
- package/dist/semantics/normalize/unreduced-type-form.js +53 -0
- package/dist/semantics/normalize/unresolvable-names.d.ts +56 -0
- package/dist/semantics/normalize/unresolvable-names.js +140 -0
- package/dist/semantics/package-sources.d.ts +16 -0
- package/dist/semantics/package-sources.js +365 -0
- package/dist/semantics/program.d.ts +151 -0
- package/dist/semantics/program.js +667 -0
- package/dist/semantics/prototype-install-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-install-source-transform.js +341 -0
- package/dist/semantics/prototype-object-class-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-object-class-source-transform.js +525 -0
- package/dist/semantics/prototype-reparenting.d.ts +50 -0
- package/dist/semantics/prototype-reparenting.js +317 -0
- package/dist/semantics/stable-checker.d.ts +10 -0
- package/dist/semantics/stable-checker.js +148 -0
- package/dist/semantics/subclass-member-overlay-transform.d.ts +35 -0
- package/dist/semantics/subclass-member-overlay-transform.js +1418 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.d.ts +4 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.js +66 -0
- package/dist/semantics/this-constructor-source-transform.d.ts +4 -0
- package/dist/semantics/this-constructor-source-transform.js +122 -0
- package/dist/semantics/uninstantiable-classes.d.ts +22 -0
- package/dist/semantics/uninstantiable-classes.js +75 -0
- package/dist/targets/cpp/balanced-units.d.ts +3 -0
- package/dist/targets/cpp/balanced-units.js +58 -0
- package/dist/targets/cpp/borrowed-call-entry.d.ts +30 -0
- package/dist/targets/cpp/borrowed-call-entry.js +68 -0
- package/dist/targets/cpp/captures.d.ts +68 -0
- package/dist/targets/cpp/captures.js +269 -0
- package/dist/targets/cpp/class-layout.d.ts +313 -0
- package/dist/targets/cpp/class-layout.js +483 -0
- package/dist/targets/cpp/class-properties/computed-method-value.d.ts +25 -0
- package/dist/targets/cpp/class-properties/computed-method-value.js +22 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.d.ts +216 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.js +917 -0
- package/dist/targets/cpp/class-properties/native-prototype.d.ts +11 -0
- package/dist/targets/cpp/class-properties/native-prototype.js +101 -0
- package/dist/targets/cpp/class-ref-transport.d.ts +12 -0
- package/dist/targets/cpp/class-ref-transport.js +32 -0
- package/dist/targets/cpp/conversions.d.ts +3 -0
- package/dist/targets/cpp/conversions.js +2027 -0
- package/dist/targets/cpp/deferral-safety.d.ts +82 -0
- package/dist/targets/cpp/deferral-safety.js +86 -0
- package/dist/targets/cpp/direct-call-receivers.d.ts +37 -0
- package/dist/targets/cpp/direct-call-receivers.js +79 -0
- package/dist/targets/cpp/document.d.ts +74 -0
- package/dist/targets/cpp/document.js +106 -0
- package/dist/targets/cpp/emit-allocation.d.ts +60 -0
- package/dist/targets/cpp/emit-allocation.js +573 -0
- package/dist/targets/cpp/emit-arrays.d.ts +119 -0
- package/dist/targets/cpp/emit-arrays.js +1047 -0
- package/dist/targets/cpp/emit-binding-reference.d.ts +17 -0
- package/dist/targets/cpp/emit-binding-reference.js +120 -0
- package/dist/targets/cpp/emit-bindings.d.ts +158 -0
- package/dist/targets/cpp/emit-bindings.js +769 -0
- package/dist/targets/cpp/emit-buffers.d.ts +156 -0
- package/dist/targets/cpp/emit-buffers.js +573 -0
- package/dist/targets/cpp/emit-callable.d.ts +230 -0
- package/dist/targets/cpp/emit-callable.js +2154 -0
- package/dist/targets/cpp/emit-carrier-members.d.ts +406 -0
- package/dist/targets/cpp/emit-carrier-members.js +1224 -0
- package/dist/targets/cpp/emit-coercion.d.ts +26 -0
- package/dist/targets/cpp/emit-coercion.js +39 -0
- package/dist/targets/cpp/emit-context.d.ts +1882 -0
- package/dist/targets/cpp/emit-context.js +904 -0
- package/dist/targets/cpp/emit-dynamic-properties.d.ts +174 -0
- package/dist/targets/cpp/emit-dynamic-properties.js +1249 -0
- package/dist/targets/cpp/emit-equality.d.ts +39 -0
- package/dist/targets/cpp/emit-equality.js +472 -0
- package/dist/targets/cpp/emit-exceptions.d.ts +104 -0
- package/dist/targets/cpp/emit-exceptions.js +513 -0
- package/dist/targets/cpp/emit-field-owner.d.ts +4 -0
- package/dist/targets/cpp/emit-field-owner.js +27 -0
- package/dist/targets/cpp/emit-in.d.ts +31 -0
- package/dist/targets/cpp/emit-in.js +426 -0
- package/dist/targets/cpp/emit-instanceof.d.ts +19 -0
- package/dist/targets/cpp/emit-instanceof.js +601 -0
- package/dist/targets/cpp/emit-integers.d.ts +68 -0
- package/dist/targets/cpp/emit-integers.js +184 -0
- package/dist/targets/cpp/emit-iterator.d.ts +100 -0
- package/dist/targets/cpp/emit-iterator.js +1137 -0
- package/dist/targets/cpp/emit-json.d.ts +73 -0
- package/dist/targets/cpp/emit-json.js +823 -0
- package/dist/targets/cpp/emit-jsx.d.ts +74 -0
- package/dist/targets/cpp/emit-jsx.js +806 -0
- package/dist/targets/cpp/emit-mixed-binary.d.ts +51 -0
- package/dist/targets/cpp/emit-mixed-binary.js +60 -0
- package/dist/targets/cpp/emit-namespaces.d.ts +101 -0
- package/dist/targets/cpp/emit-namespaces.js +133 -0
- package/dist/targets/cpp/emit-narrowing.d.ts +738 -0
- package/dist/targets/cpp/emit-narrowing.js +3967 -0
- package/dist/targets/cpp/emit-native-equality.d.ts +3 -0
- package/dist/targets/cpp/emit-native-equality.js +14 -0
- package/dist/targets/cpp/emit-native-selection.d.ts +5 -0
- package/dist/targets/cpp/emit-native-selection.js +37 -0
- package/dist/targets/cpp/emit-object-tag.d.ts +4 -0
- package/dist/targets/cpp/emit-object-tag.js +108 -0
- package/dist/targets/cpp/emit-owned-record.d.ts +2 -0
- package/dist/targets/cpp/emit-owned-record.js +15 -0
- package/dist/targets/cpp/emit-presence.d.ts +78 -0
- package/dist/targets/cpp/emit-presence.js +376 -0
- package/dist/targets/cpp/emit-properties.d.ts +105 -0
- package/dist/targets/cpp/emit-properties.js +1640 -0
- package/dist/targets/cpp/emit-record-view.d.ts +20 -0
- package/dist/targets/cpp/emit-record-view.js +354 -0
- package/dist/targets/cpp/emit-return.d.ts +5 -0
- package/dist/targets/cpp/emit-return.js +237 -0
- package/dist/targets/cpp/emit-sum-widening.d.ts +10 -0
- package/dist/targets/cpp/emit-sum-widening.js +69 -0
- package/dist/targets/cpp/emit-tonumber.d.ts +38 -0
- package/dist/targets/cpp/emit-tonumber.js +177 -0
- package/dist/targets/cpp/emit-tostring.d.ts +92 -0
- package/dist/targets/cpp/emit-tostring.js +556 -0
- package/dist/targets/cpp/emit-typeof.d.ts +49 -0
- package/dist/targets/cpp/emit-typeof.js +317 -0
- package/dist/targets/cpp/emit-union-properties.d.ts +181 -0
- package/dist/targets/cpp/emit-union-properties.js +1281 -0
- package/dist/targets/cpp/emit.d.ts +45 -0
- package/dist/targets/cpp/emit.js +2225 -0
- package/dist/targets/cpp/error-types.d.ts +4 -0
- package/dist/targets/cpp/error-types.js +11 -0
- package/dist/targets/cpp/function-source-reads.d.ts +72 -0
- package/dist/targets/cpp/function-source-reads.js +148 -0
- package/dist/targets/cpp/host/atomics.d.ts +25 -0
- package/dist/targets/cpp/host/atomics.js +63 -0
- package/dist/targets/cpp/host/core-globals.d.ts +108 -0
- package/dist/targets/cpp/host/core-globals.js +158 -0
- package/dist/targets/cpp/host/dynamic-argument-members.d.ts +42 -0
- package/dist/targets/cpp/host/dynamic-argument-members.js +61 -0
- package/dist/targets/cpp/host/emit-host-arity.d.ts +139 -0
- package/dist/targets/cpp/host/emit-host-arity.js +232 -0
- package/dist/targets/cpp/host/emit-host-invoke.d.ts +91 -0
- package/dist/targets/cpp/host/emit-host-invoke.js +1105 -0
- package/dist/targets/cpp/host/emit-host-object.d.ts +55 -0
- package/dist/targets/cpp/host/emit-host-object.js +2206 -0
- package/dist/targets/cpp/host/emit-host-properties.d.ts +69 -0
- package/dist/targets/cpp/host/emit-host-properties.js +533 -0
- package/dist/targets/cpp/host/emit-host-reflect.d.ts +4 -0
- package/dist/targets/cpp/host/emit-host-reflect.js +180 -0
- package/dist/targets/cpp/host/emit-host-value.d.ts +120 -0
- package/dist/targets/cpp/host/emit-host-value.js +392 -0
- package/dist/targets/cpp/host/host-members.d.ts +505 -0
- package/dist/targets/cpp/host/host-members.js +819 -0
- package/dist/targets/cpp/host/host-method-aliases.d.ts +30 -0
- package/dist/targets/cpp/host/host-method-aliases.js +76 -0
- package/dist/targets/cpp/host/native-protocols.d.ts +47 -0
- package/dist/targets/cpp/host/native-protocols.js +183 -0
- package/dist/targets/cpp/host/object-protocol.d.ts +351 -0
- package/dist/targets/cpp/host/object-protocol.js +671 -0
- package/dist/targets/cpp/host-namespace-reads.d.ts +83 -0
- package/dist/targets/cpp/host-namespace-reads.js +113 -0
- package/dist/targets/cpp/manifest/capabilities.d.ts +39 -0
- package/dist/targets/cpp/manifest/capabilities.js +1484 -0
- package/dist/targets/cpp/manifest.d.ts +23 -0
- package/dist/targets/cpp/manifest.js +113 -0
- package/dist/targets/cpp/native-error-base.d.ts +38 -0
- package/dist/targets/cpp/native-error-base.js +74 -0
- package/dist/targets/cpp/native-narrowing-transport.d.ts +12 -0
- package/dist/targets/cpp/native-narrowing-transport.js +151 -0
- package/dist/targets/cpp/native-selection-helpers.d.ts +11 -0
- package/dist/targets/cpp/native-selection-helpers.js +46 -0
- package/dist/targets/cpp/native-symbol-keys.d.ts +8 -0
- package/dist/targets/cpp/native-symbol-keys.js +34 -0
- package/dist/targets/cpp/ownership.d.ts +43 -0
- package/dist/targets/cpp/ownership.js +38 -0
- package/dist/targets/cpp/owning-conversion-input.d.ts +14 -0
- package/dist/targets/cpp/owning-conversion-input.js +12 -0
- package/dist/targets/cpp/property-read-claims.d.ts +62 -0
- package/dist/targets/cpp/property-read-claims.js +23 -0
- package/dist/targets/cpp/property-store-claims.d.ts +62 -0
- package/dist/targets/cpp/property-store-claims.js +26 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.d.ts +111 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.js +602 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.d.ts +133 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.js +515 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.d.ts +13 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.js +54 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.d.ts +34 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.js +1003 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.d.ts +47 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.js +250 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.d.ts +46 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.js +143 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.d.ts +335 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.js +853 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.d.ts +42 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.js +252 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.d.ts +25 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.js +182 -0
- package/dist/targets/cpp/reactive-dependencies.d.ts +140 -0
- package/dist/targets/cpp/reactive-dependencies.js +432 -0
- package/dist/targets/cpp/reactive-origins.d.ts +44 -0
- package/dist/targets/cpp/reactive-origins.js +82 -0
- package/dist/targets/cpp/records.d.ts +277 -0
- package/dist/targets/cpp/records.js +2427 -0
- package/dist/targets/cpp/recursive-containers.d.ts +43 -0
- package/dist/targets/cpp/recursive-containers.js +144 -0
- package/dist/targets/cpp/regexp-types.d.ts +56 -0
- package/dist/targets/cpp/regexp-types.js +59 -0
- package/dist/targets/cpp/substrate.d.ts +125 -0
- package/dist/targets/cpp/substrate.js +12 -0
- package/dist/targets/cpp/translation-unit.d.ts +219 -0
- package/dist/targets/cpp/translation-unit.js +2063 -0
- package/dist/targets/cpp/types.d.ts +280 -0
- package/dist/targets/cpp/types.js +1135 -0
- package/dist/targets/cpp/virtual-methods.d.ts +95 -0
- package/dist/targets/cpp/virtual-methods.js +264 -0
- package/package.json +95 -0
- package/src/targets/cpp/runtime/gea_dynamic_proxy.h +824 -0
- package/src/targets/cpp/runtime/gea_eval.h +1376 -0
- package/src/targets/cpp/runtime/gea_native_class_prototype.h +44 -0
- package/src/targets/cpp/runtime/gea_runtime.h +29222 -0
- package/src/targets/cpp/runtime/gea_runtime_builtins.cpp +55 -0
|
@@ -0,0 +1,1824 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { genericFunctionChoiceMembersOf } from './generic-function-choice.js';
|
|
3
|
+
import { layoutRelevantParameterIndices, parametersInInstanceStorage } from './structural-layout-relevance.js';
|
|
4
|
+
import { isAmbientDeclaration } from '../ambient.js';
|
|
5
|
+
export const emptySpecializationCensus = {
|
|
6
|
+
specializationsOf: () => [],
|
|
7
|
+
isGeneric: () => false,
|
|
8
|
+
specializationAt: () => null,
|
|
9
|
+
setSpecializationsAt: () => null,
|
|
10
|
+
specializationOfInstance: () => null,
|
|
11
|
+
copiesMayDifferInLayout: () => false,
|
|
12
|
+
canonicalLayoutFillings: () => null
|
|
13
|
+
};
|
|
14
|
+
const typeParametersOf = (declaration) => {
|
|
15
|
+
const withParameters = declaration;
|
|
16
|
+
return withParameters.typeParameters ?? [];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The declaration whose type parameters a node's value actually writes down.
|
|
20
|
+
*
|
|
21
|
+
* `function identity<T>(x: T): T {}` and `const identity = <T>(x: T): T => x`
|
|
22
|
+
* are the same declaration written two ways -- both name a generic function,
|
|
23
|
+
* both are instantiated per call site -- and this census keys specializations
|
|
24
|
+
* on the node that CARRIES the type parameters, which for the second spelling
|
|
25
|
+
* is the arrow function rather than the variable declaration naming it.
|
|
26
|
+
*
|
|
27
|
+
* Every consumer that asks "which copy does this declaration belong to" has to
|
|
28
|
+
* ask about the same node, or the two halves disagree: `census.ts` forks the
|
|
29
|
+
* walk here, and `identities.ts`'s `useSitePath` resolves a name to a copy
|
|
30
|
+
* here. When only one of them hopped, the arrow forked per copy while the
|
|
31
|
+
* declaration holding it stayed at the root path -- and the binding recorded
|
|
32
|
+
* there cited an allocation that exists only inside a copy.
|
|
33
|
+
*/
|
|
34
|
+
export const genericSubjectOf = (node, targetOfName) => {
|
|
35
|
+
if (!ts.isVariableDeclaration(node) || node.initializer === undefined)
|
|
36
|
+
return node;
|
|
37
|
+
if (ts.isFunctionLike(node.initializer))
|
|
38
|
+
return node.initializer;
|
|
39
|
+
if (!targetOfName || !ts.isIdentifier(node.initializer))
|
|
40
|
+
return node;
|
|
41
|
+
// An ANNOTATED binding is a cell of the annotation's own type, not a second
|
|
42
|
+
// name for the generic: `const nodeVisitor: NodeVisitor = visitNode` holds
|
|
43
|
+
// one closure over the constraints, converted into the annotation's
|
|
44
|
+
// convention, and calls through it are calls through that cell. Hopping it
|
|
45
|
+
// left the program with no cell at all for the name its reads cite.
|
|
46
|
+
if (node.type !== undefined)
|
|
47
|
+
return node;
|
|
48
|
+
// `const jsxs = jsx` -- a generic named as a VALUE. The two names denote one
|
|
49
|
+
// function, and the copies belong to whichever declaration writes the type
|
|
50
|
+
// parameters, so the alias has to fork with its target rather than hold a
|
|
51
|
+
// value of its own. It cannot hold one: `auto f = jsx;` is ill-formed C++
|
|
52
|
+
// when `jsx` is a template, whatever instantiations exist elsewhere.
|
|
53
|
+
//
|
|
54
|
+
// ONE hop, and only to a generic FUNCTION. Chaining would need a cycle guard
|
|
55
|
+
// for no case anyone writes, and widening it to any generic declaration
|
|
56
|
+
// reaches `const S = Set` -- a generic CLASS, which is bound through a host
|
|
57
|
+
// protocol keyed on its own root and breaks when a copy answers for it.
|
|
58
|
+
const target = targetOfName(node.initializer);
|
|
59
|
+
if (!target)
|
|
60
|
+
return node;
|
|
61
|
+
const subject = ts.isVariableDeclaration(target) && target.initializer !== undefined && ts.isFunctionLike(target.initializer)
|
|
62
|
+
? target.initializer
|
|
63
|
+
: target;
|
|
64
|
+
return ts.isFunctionLike(subject) && typeParametersOf(subject).length > 0 ? subject : node;
|
|
65
|
+
};
|
|
66
|
+
/** Whether this type is itself a hole. Binding one parameter to another resolves nothing, so such a pairing is not an instantiation. */
|
|
67
|
+
const isHole = (type) => (type.flags & ts.TypeFlags.TypeParameter) !== 0;
|
|
68
|
+
/**
|
|
69
|
+
* Whether a filling still has a hole ANYWHERE inside it.
|
|
70
|
+
*
|
|
71
|
+
* `isHole` alone asks only about the top: `AbstractCursor<WithId<TSchema>>`
|
|
72
|
+
* passes it, because `WithId<TSchema>` is an object type and not a parameter.
|
|
73
|
+
* The instantiation it describes is not one the program makes, though -- it is
|
|
74
|
+
* one copy of `Collection<TSchema>`'s own body writing down a reference whose
|
|
75
|
+
* argument is still open -- and minting a copy for it puts back exactly the
|
|
76
|
+
* state monomorphization exists to remove: a body walked with a parameter
|
|
77
|
+
* nothing in that copy binds. mongodb's `AbstractCursor` had seven copies and
|
|
78
|
+
* one of them was `WithId<TSchema>`; every `TSchema` inside it reached
|
|
79
|
+
* representation with no carrier.
|
|
80
|
+
*
|
|
81
|
+
* The check is the deep one because the shallow one cannot tell the two apart,
|
|
82
|
+
* and the copy a program really does make -- `AbstractCursor<WithId<Document>>`,
|
|
83
|
+
* from a call the checker itself already resolved -- is recorded from that
|
|
84
|
+
* call, not from this reference.
|
|
85
|
+
*/
|
|
86
|
+
const containsHole = (type, depth = 0) => {
|
|
87
|
+
if (isHole(type))
|
|
88
|
+
return true;
|
|
89
|
+
if (depth > 6)
|
|
90
|
+
return false;
|
|
91
|
+
if (type.isUnionOrIntersection())
|
|
92
|
+
return type.types.some((one) => containsHole(one, depth + 1));
|
|
93
|
+
// BOTH argument lists, always. An instantiated ANONYMOUS type -- a mapped
|
|
94
|
+
// alias like tsc's `Mutable<T>`, an inline object or function type -- has a
|
|
95
|
+
// `target` (the open anonymous type it was instantiated from) and NO
|
|
96
|
+
// `typeArguments`, so choosing one list by the presence of `target` read an
|
|
97
|
+
// empty list for it and called `Mutable<T>` closed. `setTextRange(updated,
|
|
98
|
+
// original)` inside `update<T extends Node>` then minted ONE copy of
|
|
99
|
+
// `setTextRange`, over the open `Mutable<T>`, instead of one per copy of
|
|
100
|
+
// `update` -- 171 tsc self-compile rows, every one a callee whose carrier
|
|
101
|
+
// was the constraint image while the call wanted the instantiation.
|
|
102
|
+
const reference = type;
|
|
103
|
+
const args = [...(reference.typeArguments ?? []), ...(type.aliasTypeArguments ?? [])];
|
|
104
|
+
return args.some((one) => containsHole(one, depth + 1));
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* The declaration whose body a set of type parameters belongs to.
|
|
108
|
+
*
|
|
109
|
+
* A type parameter's own declaration is a `TypeParameter` node whose parent is
|
|
110
|
+
* the generic. That parent is what gets copied, so it is what a specialization
|
|
111
|
+
* is recorded against.
|
|
112
|
+
*/
|
|
113
|
+
/**
|
|
114
|
+
* A filling that is not a layout: `any`, or one still mentioning a type
|
|
115
|
+
* parameter.
|
|
116
|
+
*
|
|
117
|
+
* `containsHole` walks type ARGUMENTS, so it sees `Box<T>` but not `I["out"]`
|
|
118
|
+
* -- an indexed access keeps its parameter in `objectType`, and a conditional
|
|
119
|
+
* keeps one in each branch. hono records `HonoRequest<any, I["out"]>` as a
|
|
120
|
+
* copy through exactly that gap: `P` was substituted and `I` was not.
|
|
121
|
+
*
|
|
122
|
+
* Such a copy states no layout, so it cannot be EVIDENCE of one either -- it
|
|
123
|
+
* must neither force copies apart nor be the shape they are folded onto. It is
|
|
124
|
+
* deliberately not routed through `containsHole` itself, which decides whether
|
|
125
|
+
* a copy is recorded at all: `Context.req` is declared `HonoRequest<P, I['out']>`
|
|
126
|
+
* and dropping that copy leaves the field with no censused carrier.
|
|
127
|
+
*/
|
|
128
|
+
const openFilling = (type, depth = 0) => {
|
|
129
|
+
if (type === undefined)
|
|
130
|
+
return false;
|
|
131
|
+
if ((type.flags & (ts.TypeFlags.Any | ts.TypeFlags.TypeParameter)) !== 0)
|
|
132
|
+
return true;
|
|
133
|
+
if (depth > 6)
|
|
134
|
+
return false;
|
|
135
|
+
if (type.isUnionOrIntersection())
|
|
136
|
+
return type.types.some((one) => openFilling(one, depth + 1));
|
|
137
|
+
if ((type.flags & ts.TypeFlags.IndexedAccess) !== 0) {
|
|
138
|
+
const indexed = type;
|
|
139
|
+
return openFilling(indexed.objectType, depth + 1) || openFilling(indexed.indexType, depth + 1);
|
|
140
|
+
}
|
|
141
|
+
if ((type.flags & ts.TypeFlags.Conditional) !== 0) {
|
|
142
|
+
const conditional = type;
|
|
143
|
+
return openFilling(conditional.checkType, depth + 1) || openFilling(conditional.extendsType, depth + 1);
|
|
144
|
+
}
|
|
145
|
+
if ((type.flags & ts.TypeFlags.Index) !== 0)
|
|
146
|
+
return openFilling(type.type, depth + 1);
|
|
147
|
+
if ((type.flags & ts.TypeFlags.Substitution) !== 0)
|
|
148
|
+
return openFilling(type.baseType, depth + 1);
|
|
149
|
+
const reference = type;
|
|
150
|
+
return [...(reference.typeArguments ?? []), ...(type.aliasTypeArguments ?? [])].some((one) => openFilling(one, depth + 1));
|
|
151
|
+
};
|
|
152
|
+
const ownerOf = (parameter) => {
|
|
153
|
+
const parent = parameter?.parent;
|
|
154
|
+
if (!parent)
|
|
155
|
+
return null;
|
|
156
|
+
// Only the kinds whose body or shape is actually copied. A `JSDocTemplateTag`
|
|
157
|
+
// or an `infer` position also parents a type parameter and neither names
|
|
158
|
+
// something a specialization can be recorded against.
|
|
159
|
+
return ts.isClassLike(parent) || ts.isInterfaceDeclaration(parent) || ts.isTypeAliasDeclaration(parent) || ts.isFunctionLike(parent)
|
|
160
|
+
? parent
|
|
161
|
+
: null;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Pair a generic type with the instantiated one the checker produced from it,
|
|
165
|
+
* recording what each parameter was filled with.
|
|
166
|
+
*
|
|
167
|
+
* This walks the two types in lockstep rather than reading the checker's
|
|
168
|
+
* internal type mapper, which is not public API. The shapes are congruent by
|
|
169
|
+
* construction -- one *is* the other with holes filled -- so the walk is a
|
|
170
|
+
* structural comparison with no inference in it: at every position where the
|
|
171
|
+
* generic side is a hole, the concrete side is that hole's filling.
|
|
172
|
+
*
|
|
173
|
+
* Unions and intersections are deliberately not walked. `T | string` against
|
|
174
|
+
* `number | string` has no unique alignment -- the arms are a set, not a
|
|
175
|
+
* sequence -- and picking one would record a binding the language never made.
|
|
176
|
+
*/
|
|
177
|
+
const carriesAbsence = (type) => type.isUnion() && type.types.some((arm) => (arm.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null)) !== 0);
|
|
178
|
+
/**
|
|
179
|
+
* A union with its absence arms removed. Spelled by hand rather than through
|
|
180
|
+
* `getNonNullableType`: for an UNCONSTRAINED parameter the checker spells
|
|
181
|
+
* `NonNullable<T>` as the intersection `T & {}`, which `isHole` does not
|
|
182
|
+
* recognise -- so `maybe<T>(value: T | undefined): T | undefined` bound `T`
|
|
183
|
+
* nowhere, minted no copy, and every direct call of it was refused at lowering
|
|
184
|
+
* as a generic set with no closed family. A constrained `U extends string`
|
|
185
|
+
* survives `getNonNullableType` as itself, which is the only reason hono's
|
|
186
|
+
* `c.json` shape ever bound. One present arm is that arm; several fall back to
|
|
187
|
+
* the checker's spelling, which for a closed type is the union of them.
|
|
188
|
+
*/
|
|
189
|
+
const presentOf = (checker, type) => {
|
|
190
|
+
if (!type.isUnion())
|
|
191
|
+
return type;
|
|
192
|
+
const present = type.types.filter((arm) => (arm.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Null)) === 0);
|
|
193
|
+
const sole = present.length === 1 ? present[0] : undefined;
|
|
194
|
+
return sole ?? checker.getNonNullableType(type);
|
|
195
|
+
};
|
|
196
|
+
const unify = (checker, generic, concrete, depth, record, recordPair = null) => {
|
|
197
|
+
if (depth > 8 || generic === concrete)
|
|
198
|
+
return;
|
|
199
|
+
if (isHole(generic)) {
|
|
200
|
+
record(generic, concrete);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// A composite with a hole inside, beside the closed type the checker built
|
|
204
|
+
// for it: the pair a copy answers `fillingOf` from.
|
|
205
|
+
if (recordPair && containsHole(generic))
|
|
206
|
+
recordPair(generic, concrete);
|
|
207
|
+
// An OPTIONALITY MARKER is not content. `status?: U` is read as `U |
|
|
208
|
+
// undefined` and its instantiation as `ContentfulStatusCode | undefined`:
|
|
209
|
+
// one arm on the left, many on the right, so the positional union walk
|
|
210
|
+
// below declines and `U` binds nothing. TypeScript contributes that
|
|
211
|
+
// `undefined` on BOTH sides for the `?`, so it belongs to neither union's
|
|
212
|
+
// content -- dropping it from both restores the congruence the walk needs.
|
|
213
|
+
// hono's `c.json({ hello: 'world' })` is exactly this shape, and `U`
|
|
214
|
+
// failing to bind discarded the ENTIRE instantiation, `T` included, which
|
|
215
|
+
// is what left `Context.json` an uninitialized field.
|
|
216
|
+
//
|
|
217
|
+
// Only when both sides carry it. A lone `undefined` on the concrete side is
|
|
218
|
+
// a hole's filling, not a marker.
|
|
219
|
+
if (carriesAbsence(generic) && carriesAbsence(concrete)) {
|
|
220
|
+
const genericPresent = presentOf(checker, generic);
|
|
221
|
+
const concretePresent = presentOf(checker, concrete);
|
|
222
|
+
if (genericPresent !== generic || concretePresent !== concrete) {
|
|
223
|
+
unify(checker, genericPresent, concretePresent, depth + 1, record, recordPair);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// The marker COLLAPSED under instantiation. `T | undefined` with `T` bound
|
|
228
|
+
// to `undefined` is one member, `undefined`, and the checker does infer
|
|
229
|
+
// exactly that: tsc's `return toSearchResult(/*value*/ undefined)` resolves
|
|
230
|
+
// to `(value: undefined): SearchResult<undefined>`. A generic union whose
|
|
231
|
+
// only present arm is a hole, against a concrete type carrying no absence,
|
|
232
|
+
// is that collapse -- the whole concrete type is the hole's filling
|
|
233
|
+
// (`unknown` and `any` absorb the marker the same way). Nothing else reaches
|
|
234
|
+
// here: an optional parameter or a `| undefined` return keeps its marker
|
|
235
|
+
// under every non-absorbing filling.
|
|
236
|
+
if (carriesAbsence(generic) && !carriesAbsence(concrete)) {
|
|
237
|
+
const sole = presentOf(checker, generic);
|
|
238
|
+
if (isHole(sole)) {
|
|
239
|
+
record(sole, concrete);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Two instantiations of one generic type ALIAS. The alias's arguments are
|
|
244
|
+
// not `typeArguments` (see the reference branch below) but the checker
|
|
245
|
+
// keeps them as `aliasTypeArguments`, positionally against the alias's own
|
|
246
|
+
// parameters -- `SearchResult<T>` against `SearchResult<undefined>` names
|
|
247
|
+
// `T`'s filling directly, where walking into the aliased object literal's
|
|
248
|
+
// members would not (members are not walked here). Read before the
|
|
249
|
+
// reference branch so an alias over a reference still pairs by the alias.
|
|
250
|
+
if (generic.aliasSymbol !== undefined &&
|
|
251
|
+
generic.aliasSymbol === concrete.aliasSymbol &&
|
|
252
|
+
generic.aliasTypeArguments !== undefined &&
|
|
253
|
+
concrete.aliasTypeArguments !== undefined) {
|
|
254
|
+
for (let index = 0; index < Math.min(generic.aliasTypeArguments.length, concrete.aliasTypeArguments.length); index += 1) {
|
|
255
|
+
const left = generic.aliasTypeArguments[index];
|
|
256
|
+
const right = concrete.aliasTypeArguments[index];
|
|
257
|
+
if (left && right)
|
|
258
|
+
unify(checker, left, right, depth + 1, record, recordPair);
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const genericReference = generic;
|
|
263
|
+
const concreteReference = concrete;
|
|
264
|
+
const genericArguments = genericReference.typeArguments;
|
|
265
|
+
const concreteArguments = concreteReference.typeArguments;
|
|
266
|
+
if ((generic.flags & ts.TypeFlags.Object) !== 0 &&
|
|
267
|
+
(concrete.flags & ts.TypeFlags.Object) !== 0 &&
|
|
268
|
+
genericReference.target !== undefined &&
|
|
269
|
+
genericReference.target === concreteReference.target &&
|
|
270
|
+
// Only when the arguments are actually READABLE here. Two instantiations
|
|
271
|
+
// of a generic type ALIAS share a `target` exactly as two references to a
|
|
272
|
+
// generic interface do, but an alias's arguments live in the mapper the
|
|
273
|
+
// checker instantiated it with, not in `typeArguments` -- so this branch
|
|
274
|
+
// matched, found an empty argument list, and returned having unified
|
|
275
|
+
// nothing. hono's `ErrorHandler<E>` against `ErrorHandler<any>` is that
|
|
276
|
+
// shape, and stopping there is why `compose<E>` was recorded with `E`
|
|
277
|
+
// bound by nothing. Falling through to the signature walk below reaches
|
|
278
|
+
// the same hole the long way, through `Context<E>` in the parameter list.
|
|
279
|
+
genericArguments !== undefined &&
|
|
280
|
+
concreteArguments !== undefined) {
|
|
281
|
+
for (let index = 0; index < Math.min(genericArguments.length, concreteArguments.length); index += 1) {
|
|
282
|
+
const left = genericArguments[index];
|
|
283
|
+
const right = concreteArguments[index];
|
|
284
|
+
if (left && right)
|
|
285
|
+
unify(checker, left, right, depth + 1, record, recordPair);
|
|
286
|
+
}
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
// A UNION on both sides, member for member. `onError?: ErrorHandler<E>` is
|
|
290
|
+
// read as `ErrorHandler<E> | undefined`, and a union carries no call
|
|
291
|
+
// signature of its own -- so without this the hole inside it was never
|
|
292
|
+
// reached, and hono's `compose<E>` was called twice with `E` bound by
|
|
293
|
+
// nothing at all: no instantiation was recorded, `compose` was registered
|
|
294
|
+
// as a generic with no copies, and `census.ts` walks one of those NOT AT
|
|
295
|
+
// ALL. The whole of `compose.ts` published a single `module-evaluate`, and
|
|
296
|
+
// emission refused the read as a declaration this program never introduces.
|
|
297
|
+
//
|
|
298
|
+
// Paired POSITIONALLY, and only when the counts match. The concrete union
|
|
299
|
+
// is an instantiation of the generic one, so the checker's own member order
|
|
300
|
+
// corresponds -- but a member can collapse under instantiation (`T |
|
|
301
|
+
// undefined` with `T` bound to `undefined` is one member), and a pairing
|
|
302
|
+
// across a collapse would bind a hole to a member that is not its own.
|
|
303
|
+
if (generic.isUnion() && concrete.isUnion() && generic.types.length === concrete.types.length) {
|
|
304
|
+
for (let index = 0; index < generic.types.length; index += 1) {
|
|
305
|
+
const left = generic.types[index];
|
|
306
|
+
const right = concrete.types[index];
|
|
307
|
+
if (left && right)
|
|
308
|
+
unify(checker, left, right, depth + 1, record, recordPair);
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
unifySignatures(checker, generic.getCallSignatures(), concrete.getCallSignatures(), depth, record, recordPair);
|
|
313
|
+
unifySignatures(checker, generic.getConstructSignatures(), concrete.getConstructSignatures(), depth, record, recordPair);
|
|
314
|
+
};
|
|
315
|
+
/**
|
|
316
|
+
* One signature list against another.
|
|
317
|
+
*
|
|
318
|
+
* Only a single-signature pair is walked. An overloaded type's signatures are
|
|
319
|
+
* not ordered by anything the instantiation preserves, so aligning the nth with
|
|
320
|
+
* the nth would pair a generic's second overload with a concrete's second for
|
|
321
|
+
* no reason beyond position.
|
|
322
|
+
*/
|
|
323
|
+
const unifySignatures = (checker, generics, concretes, depth, record, recordPair = null) => {
|
|
324
|
+
const generic = generics[0];
|
|
325
|
+
const concrete = concretes[0];
|
|
326
|
+
if (generics.length !== 1 || concretes.length !== 1 || !generic || !concrete)
|
|
327
|
+
return;
|
|
328
|
+
unify(checker, generic.getReturnType(), concrete.getReturnType(), depth + 1, record, recordPair);
|
|
329
|
+
// `this` IS a parameter -- ECMA-262 gives it a binding in the function
|
|
330
|
+
// environment like any other -- and it is the only one `Signature.parameters`
|
|
331
|
+
// leaves out. A generic whose type parameter appears ONLY there was therefore
|
|
332
|
+
// never bound by this walk. hono's `export function match<R extends
|
|
333
|
+
// Router<T>, T>(this: R, method: string, path: string)` is the case: `T` is
|
|
334
|
+
// bound from the return type and `R` stayed open, so `fromValueUse` saw one
|
|
335
|
+
// of two parameters filled, minted no copy, and `RegExpRouter`'s field
|
|
336
|
+
// initializer `match: typeof match<Router<T>, T> = match` then read the ROOT
|
|
337
|
+
// declaration -- which the program never introduces, because a generic this
|
|
338
|
+
// program defines is recorded per copy and never at the root, and emission
|
|
339
|
+
// refused the read by name.
|
|
340
|
+
//
|
|
341
|
+
// `thisParameter` is not on the public `Signature`, so it is reached the same
|
|
342
|
+
// guarded way `structural-array-element.ts` reaches `getUnionType`.
|
|
343
|
+
const genericThis = generic.thisParameter;
|
|
344
|
+
const concreteThis = concrete.thisParameter;
|
|
345
|
+
if (genericThis && concreteThis) {
|
|
346
|
+
const genericThisType = typeOfParameter(checker, genericThis);
|
|
347
|
+
const concreteThisType = typeOfParameter(checker, concreteThis);
|
|
348
|
+
if (genericThisType && concreteThisType)
|
|
349
|
+
unify(checker, genericThisType, concreteThisType, depth + 1, record, recordPair);
|
|
350
|
+
}
|
|
351
|
+
for (let index = 0; index < Math.min(generic.parameters.length, concrete.parameters.length); index += 1) {
|
|
352
|
+
const left = generic.parameters[index];
|
|
353
|
+
const right = concrete.parameters[index];
|
|
354
|
+
if (!left || !right)
|
|
355
|
+
continue;
|
|
356
|
+
const leftType = typeOfParameter(checker, left);
|
|
357
|
+
const rightType = typeOfParameter(checker, right);
|
|
358
|
+
if (leftType && rightType)
|
|
359
|
+
unify(checker, leftType, rightType, depth + 1, record, recordPair);
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
/** A parameter symbol's declared type, or `null` when the symbol has no declaration to read it at. */
|
|
363
|
+
const typeOfParameter = (checker, parameter) => {
|
|
364
|
+
const at = parameter.valueDeclaration ?? parameter.declarations?.[0];
|
|
365
|
+
return at ? checker.getTypeOfSymbolAtLocation(parameter, at) : null;
|
|
366
|
+
};
|
|
367
|
+
// Every `checker.getTypeAtLocation` / `Signature.getReturnType()` /
|
|
368
|
+
// `checker.getTypeOfSymbolAtLocation` call below (`unify`, `unifySignatures`,
|
|
369
|
+
// `typeOfParameter`, `induceFromHeritage`, `genericSignatureOf`, `fromCall`,
|
|
370
|
+
// `fromTypeReference`, the `visit` walk) answers "what did the LANGUAGE
|
|
371
|
+
// resolve this generic/heritage/call site to", not "what does this node
|
|
372
|
+
// hold" -- there is no census question to ask. This module's own header says
|
|
373
|
+
// why directly: it "answers it before anything is normalized, because the
|
|
374
|
+
// census has to know how many copies of each body to emit before it emits
|
|
375
|
+
// any". `frontend.ts`'s `runFrontend` computes `instantiations` and
|
|
376
|
+
// `specializations` first, ahead of the parameter/return/local/field binding
|
|
377
|
+
// fixpoint those two feed -- so at every site below, no census instance
|
|
378
|
+
// exists yet to convert a checker call to. Left as direct checker calls,
|
|
379
|
+
// verified by reading `frontend.ts`'s call order. See the matching note in
|
|
380
|
+
// `instantiation.ts`.
|
|
381
|
+
export const censusSpecializations = (checker, sourceFiles, reachable, namespacePaths) => {
|
|
382
|
+
// Per generic declaration: the instantiations seen so far, each a tuple of
|
|
383
|
+
// the types filling its parameters, in declaration order. Tuples are compared
|
|
384
|
+
// by the identity of the types in them -- the checker interns types, so two
|
|
385
|
+
// spellings of one type are one object and dedupe without a key.
|
|
386
|
+
const tuples = new Map();
|
|
387
|
+
// A site records the fillings it was *written* with, holes included, rather
|
|
388
|
+
// than the ordinal they resolved to. `Base<T>` inside `Mid<T>` denotes a
|
|
389
|
+
// different copy of `Base` in every copy of `Mid`, so no single ordinal
|
|
390
|
+
// belongs to the node; it is looked up when the site is read, from fillings
|
|
391
|
+
// the asking copy has substituted for itself.
|
|
392
|
+
const sites = new Map();
|
|
393
|
+
// The same, for a call through a choice of generic functions: one site per
|
|
394
|
+
// member, all keyed by the one call node. See `setSpecializationsAt`.
|
|
395
|
+
const setSites = new Map();
|
|
396
|
+
// The checker's own spelling of each recorded instantiation, by ordinal, for
|
|
397
|
+
// the copies that have one. Kept beside `tuples` rather than in it so the
|
|
398
|
+
// tuple stays the identity -- two sites spelling one instantiation are one
|
|
399
|
+
// copy, and whichever of them was seen first supplies the spelling.
|
|
400
|
+
const spellings = new Map();
|
|
401
|
+
// The same, for a copy minted from a call: the open signature beside the one
|
|
402
|
+
// the checker resolved that call to.
|
|
403
|
+
const signaturePairs = new Map();
|
|
404
|
+
// The same, for the composite fillings a call-minted copy's frame closes: see `Specialization.fillingOf`.
|
|
405
|
+
const compositeFillings = new Map();
|
|
406
|
+
/**
|
|
407
|
+
* A spelling for a copy that MAY NOT EXIST, held against its tuple.
|
|
408
|
+
*
|
|
409
|
+
* A call's resolved return type is a spelling the checker has already
|
|
410
|
+
* computed for an instantiation the program makes -- `db.collection<DataKey>(
|
|
411
|
+
* ...)` really does produce `Collection<DataKey>` -- and that spelling is the
|
|
412
|
+
* one thing `structural-instantiated-member.ts` needs to read a copy's
|
|
413
|
+
* members with the hole closed. What it is NOT is evidence that a copy should
|
|
414
|
+
* EXIST. A method on a generic class names its own class in its return type
|
|
415
|
+
* (`Hono.get` returns `Hono<E, S, MergePath<...>, ...>`), so minting from one
|
|
416
|
+
* manufactures a copy per call site that nothing in the program instantiates:
|
|
417
|
+
* three of hono's own class-property arrows lost their carriers to copies
|
|
418
|
+
* minted exactly that way, and a program that certified stopped certifying.
|
|
419
|
+
*
|
|
420
|
+
* So the spelling waits here, keyed by the tuple rather than by an ordinal,
|
|
421
|
+
* and `tupleOrdinal` claims it if and when a site that really does
|
|
422
|
+
* instantiate mints that copy. Order-independent by construction, which
|
|
423
|
+
* matters: the copy `db.collection<DataKey>` returns is minted by the
|
|
424
|
+
* fixpoint round AFTER this census sees the call, so a back-fill that only
|
|
425
|
+
* wrote to existing ordinals would answer nothing at all.
|
|
426
|
+
*/
|
|
427
|
+
const deferredSpellings = new Map();
|
|
428
|
+
/**
|
|
429
|
+
* Per ordinal: does anything in the program actually MINT this copy?
|
|
430
|
+
*
|
|
431
|
+
* A written `Token<unknown>` in `string | Token<unknown> | null` states a
|
|
432
|
+
* type a value may be viewed AT; `new Token<number>()` states a value that
|
|
433
|
+
* exists. Only the second is a layout. The distinction is invisible while
|
|
434
|
+
* one class serves every filling and decisive once copies can split: made a
|
|
435
|
+
* separate struct, the union arm stops admitting the only value that ever
|
|
436
|
+
* reaches it ("a dynamic value admitted by no union arm", measured on
|
|
437
|
+
* `stated-open-union-preserves-closed-arms.ts`), while folding a copy the
|
|
438
|
+
* program really does construct and write through corrupts it instead
|
|
439
|
+
* (`generic-class-at-a-top-type-and-a-concrete-type.ts`). Two programs of
|
|
440
|
+
* the same shape needing opposite answers is what says the shape is not
|
|
441
|
+
* the question -- provenance is.
|
|
442
|
+
*
|
|
443
|
+
* `true` wins over `false`: one construction site is enough, and every path
|
|
444
|
+
* but a bare type-reference annotation counts as one.
|
|
445
|
+
*/
|
|
446
|
+
const constructions = new Map();
|
|
447
|
+
const deferredSpellingFor = (declaration, tuple) => deferredSpellings.get(declaration)?.find((entry) => entry.tuple.length === tuple.length && entry.tuple.every((t, i) => t === tuple[i]))
|
|
448
|
+
?.instantiated ?? null;
|
|
449
|
+
const tupleOrdinal = (declaration, tuple, instantiated = null, signatures = null, fillings = null, constructs = true) => {
|
|
450
|
+
const minted = constructions.get(declaration) ?? [];
|
|
451
|
+
const seen = tuples.get(declaration) ?? [];
|
|
452
|
+
const spelled = spellings.get(declaration) ?? [];
|
|
453
|
+
const paired = signaturePairs.get(declaration) ?? [];
|
|
454
|
+
const filled = compositeFillings.get(declaration) ?? [];
|
|
455
|
+
const existing = seen.findIndex((candidate) => candidate.length === tuple.length && candidate.every((t, i) => t === tuple[i]));
|
|
456
|
+
// A spelling this site does not carry may still have been computed for this
|
|
457
|
+
// exact tuple somewhere the program never instantiated from; see
|
|
458
|
+
// `deferredSpellings`.
|
|
459
|
+
const spelling = instantiated ?? deferredSpellingFor(declaration, tuple);
|
|
460
|
+
if (existing >= 0) {
|
|
461
|
+
if (spelling && !spelled[existing]) {
|
|
462
|
+
spelled[existing] = spelling;
|
|
463
|
+
spellings.set(declaration, spelled);
|
|
464
|
+
}
|
|
465
|
+
if (signatures && !paired[existing]) {
|
|
466
|
+
paired[existing] = signatures;
|
|
467
|
+
signaturePairs.set(declaration, paired);
|
|
468
|
+
}
|
|
469
|
+
if (fillings && !filled[existing]) {
|
|
470
|
+
filled[existing] = fillings;
|
|
471
|
+
compositeFillings.set(declaration, filled);
|
|
472
|
+
}
|
|
473
|
+
if (constructs && !minted[existing]) {
|
|
474
|
+
minted[existing] = true;
|
|
475
|
+
constructions.set(declaration, minted);
|
|
476
|
+
}
|
|
477
|
+
return existing;
|
|
478
|
+
}
|
|
479
|
+
minted.push(constructs);
|
|
480
|
+
constructions.set(declaration, minted);
|
|
481
|
+
seen.push([...tuple]);
|
|
482
|
+
tuples.set(declaration, seen);
|
|
483
|
+
spelled.push(spelling);
|
|
484
|
+
spellings.set(declaration, spelled);
|
|
485
|
+
paired.push(signatures);
|
|
486
|
+
signaturePairs.set(declaration, paired);
|
|
487
|
+
filled.push(fillings);
|
|
488
|
+
compositeFillings.set(declaration, filled);
|
|
489
|
+
return seen.length - 1;
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Note that a copy already recorded is MINTED, not merely named.
|
|
493
|
+
*
|
|
494
|
+
* The walk order decides which site sees a tuple first, and an annotation
|
|
495
|
+
* frequently wins: `(handle: Handle<Uint8Array>) => ...` is written below
|
|
496
|
+
* the `new Handle<T>(this)` that actually builds one, but that `new` is
|
|
497
|
+
* still open at the time and only closes in the fixpoint below -- which
|
|
498
|
+
* skips a tuple it already has. Without this the construction fact is lost
|
|
499
|
+
* to the order of two lines.
|
|
500
|
+
*/
|
|
501
|
+
const markConstructed = (declaration, ordinal) => {
|
|
502
|
+
const minted = constructions.get(declaration) ?? [];
|
|
503
|
+
if (minted[ordinal] === true)
|
|
504
|
+
return;
|
|
505
|
+
minted[ordinal] = true;
|
|
506
|
+
constructions.set(declaration, minted);
|
|
507
|
+
};
|
|
508
|
+
/** The copy whose arguments are exactly these, or `null` when the program makes no such instantiation. */
|
|
509
|
+
const ordinalOfArguments = (declaration, args) => {
|
|
510
|
+
const seen = tuples.get(declaration) ?? [];
|
|
511
|
+
const found = seen.findIndex((candidate) => candidate.length === args.length && candidate.every((t, index) => t === args[index]));
|
|
512
|
+
return found >= 0 ? found : null;
|
|
513
|
+
};
|
|
514
|
+
/**
|
|
515
|
+
* The instantiations one recorded instantiation induces through its heritage.
|
|
516
|
+
*
|
|
517
|
+
* `class ReactiveComponent<Root> extends Component<Root> {}` spells no
|
|
518
|
+
* concrete argument anywhere, so the syntactic walk sees a hole and records
|
|
519
|
+
* nothing for `Component`. The program instantiates it all the same -- once
|
|
520
|
+
* per copy of `ReactiveComponent` -- and answering "no copies" is not a
|
|
521
|
+
* conservative answer here, it is a wrong one: `census.ts` walks a generic
|
|
522
|
+
* with no copies *not at all*, so the base publishes no class evaluation, no
|
|
523
|
+
* instance carrier and no construct convention, and every derived class whose
|
|
524
|
+
* heritage resolves to it finds nothing published. Enumeration has to be
|
|
525
|
+
* closed under what a recorded copy induces, not stop at what one source line
|
|
526
|
+
* spells out.
|
|
527
|
+
*
|
|
528
|
+
* Only a filling this copy itself binds is substituted. `extends
|
|
529
|
+
* Base<Wrapper<T>>` leaves the hole *inside* an argument, and filling that
|
|
530
|
+
* needs a type instantiated -- something the public checker API does not
|
|
531
|
+
* offer -- so nothing is recorded and the base stays honestly uninstantiated.
|
|
532
|
+
*/
|
|
533
|
+
const induceFromHeritage = (declaration, bound, depth) => {
|
|
534
|
+
if (depth > 8 || !ts.isClassLike(declaration))
|
|
535
|
+
return;
|
|
536
|
+
const base = declaration.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
|
|
537
|
+
if (!base)
|
|
538
|
+
return;
|
|
539
|
+
const reference = checker.getTypeAtLocation(base);
|
|
540
|
+
const parameters = reference.target?.typeParameters;
|
|
541
|
+
const args = reference.typeArguments;
|
|
542
|
+
if (!parameters || !args)
|
|
543
|
+
return;
|
|
544
|
+
const owner = ownerOf(parameters[0]?.getSymbol()?.declarations?.[0]);
|
|
545
|
+
if (!owner)
|
|
546
|
+
return;
|
|
547
|
+
const induced = new Map();
|
|
548
|
+
for (let index = 0; index < Math.min(parameters.length, args.length); index += 1) {
|
|
549
|
+
const symbol = parameters[index]?.getSymbol();
|
|
550
|
+
const filling = args[index];
|
|
551
|
+
if (!symbol || !filling)
|
|
552
|
+
return;
|
|
553
|
+
const hole = filling !== undefined && isHole(filling) ? filling.getSymbol() : null;
|
|
554
|
+
const resolved = hole ? bound.get(hole) : filling;
|
|
555
|
+
if (!resolved || containsHole(resolved))
|
|
556
|
+
return;
|
|
557
|
+
induced.set(symbol, resolved);
|
|
558
|
+
}
|
|
559
|
+
recordTuple(owner, induced, null, depth + 1);
|
|
560
|
+
};
|
|
561
|
+
/** Record one instantiation, given the owner and the fillings keyed by parameter symbol. */
|
|
562
|
+
const recordTuple = (declaration, bound, at, depth = 0, instantiated = null, signatures = null, spellingOnly = false, fillings = null, collect = null, constructs = true) => {
|
|
563
|
+
const parameters = typeParametersOf(declaration);
|
|
564
|
+
if (parameters.length === 0)
|
|
565
|
+
return;
|
|
566
|
+
const tuple = [];
|
|
567
|
+
// Inference does not report a filling for a defaulted type parameter when
|
|
568
|
+
// the caller omits every value argument that mentions it. That absence is
|
|
569
|
+
// not an open hole: the declaration itself says what the language fills
|
|
570
|
+
// there. `Context.json<T, U = ContentfulStatusCode>(object: T, status?: U)`
|
|
571
|
+
// is the measured case -- the call binds T from `object`, omits `status`,
|
|
572
|
+
// and therefore reaches the declared default for U. Requiring inference
|
|
573
|
+
// evidence for both discarded the entire specialization, so census walked
|
|
574
|
+
// no method body and the generated class had no `json` implementation.
|
|
575
|
+
//
|
|
576
|
+
// Defaults are resolved in declaration order. A direct reference to an
|
|
577
|
+
// earlier parameter (`U = T`) can therefore reuse that earlier filling.
|
|
578
|
+
// A composite default that still contains a hole stays open and is refused
|
|
579
|
+
// by the existing deep `containsHole` check below; inventing a checker
|
|
580
|
+
// instantiation for it would exceed the public API this pass deliberately
|
|
581
|
+
// confines itself to.
|
|
582
|
+
const resolved = new Map(bound);
|
|
583
|
+
for (const parameter of parameters) {
|
|
584
|
+
const symbol = checker.getSymbolAtLocation(parameter.name);
|
|
585
|
+
let filling = symbol ? resolved.get(symbol) : undefined;
|
|
586
|
+
if (!filling && parameter.default) {
|
|
587
|
+
const statedDefault = checker.getTypeFromTypeNode(parameter.default);
|
|
588
|
+
const defaultSymbol = isHole(statedDefault) ? statedDefault.getSymbol() : undefined;
|
|
589
|
+
filling = isHole(statedDefault) ? (defaultSymbol ? resolved.get(defaultSymbol) : undefined) : statedDefault;
|
|
590
|
+
}
|
|
591
|
+
// A position this site binds with nothing at all is not a partial
|
|
592
|
+
// instantiation, it is no instantiation: nothing downstream could fill
|
|
593
|
+
// it, so neither the tuple nor the site is worth recording.
|
|
594
|
+
if (!filling)
|
|
595
|
+
return;
|
|
596
|
+
tuple.push(filling);
|
|
597
|
+
if (symbol)
|
|
598
|
+
resolved.set(symbol, filling);
|
|
599
|
+
}
|
|
600
|
+
// The site is recorded whether or not its fillings are concrete. A hole
|
|
601
|
+
// here is a parameter of some *enclosing* generic, and the copy that
|
|
602
|
+
// encloses this one substitutes it when it reads the site back. Only a
|
|
603
|
+
// concrete tuple mints a copy, because a copy with the hole still open is
|
|
604
|
+
// the state monomorphization exists to remove.
|
|
605
|
+
if (at)
|
|
606
|
+
sites.set(at, { declaration, fillings: tuple });
|
|
607
|
+
if (collect)
|
|
608
|
+
collect(tuple);
|
|
609
|
+
if (tuple.some((filling) => containsHole(filling)))
|
|
610
|
+
return;
|
|
611
|
+
// A spelling with no instantiating site behind it is REMEMBERED, never
|
|
612
|
+
// recorded: it says how a copy would be spelled, not that the program makes
|
|
613
|
+
// one. See `deferredSpellings`.
|
|
614
|
+
if (spellingOnly) {
|
|
615
|
+
if (!instantiated)
|
|
616
|
+
return;
|
|
617
|
+
const held = deferredSpellings.get(declaration) ?? [];
|
|
618
|
+
if (!held.some((entry) => entry.tuple.length === tuple.length && entry.tuple.every((t, i) => t === tuple[i]))) {
|
|
619
|
+
held.push({ tuple: [...tuple], instantiated });
|
|
620
|
+
deferredSpellings.set(declaration, held);
|
|
621
|
+
}
|
|
622
|
+
const existing = ordinalOfArguments(declaration, tuple);
|
|
623
|
+
if (existing !== null)
|
|
624
|
+
tupleOrdinal(declaration, tuple, instantiated, signatures, fillings, constructs);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
tupleOrdinal(declaration, tuple, instantiated, signatures, fillings, constructs);
|
|
628
|
+
induceFromHeritage(declaration, resolved, depth);
|
|
629
|
+
};
|
|
630
|
+
// Keyed by the instantiation itself: every mention of `RegExpRouter<[H,
|
|
631
|
+
// RouterRoute]>` resolves to the one type object, and resolving a
|
|
632
|
+
// reference's members is not free.
|
|
633
|
+
const memberFillings = new Map();
|
|
634
|
+
/**
|
|
635
|
+
* The composite fillings a copy minted from a written type REFERENCE closes.
|
|
636
|
+
*
|
|
637
|
+
* `Specialization.fillingOf` is the one authority `filledBy` here and
|
|
638
|
+
* `createPathSubstitution` (structural-generics.ts) close a composite hole
|
|
639
|
+
* from. A copy minted from a CALL gets those pairs for free: the checker
|
|
640
|
+
* built the resolved signature beside the open one and `unifySignatures`
|
|
641
|
+
* walks the two in lockstep. A class copy is minted here instead, from a
|
|
642
|
+
* reference that pairs only the type ARGUMENTS -- so a composite spelled
|
|
643
|
+
* over the class's own parameter had no image, every call inside the body
|
|
644
|
+
* whose instantiation mentions one stayed open, and `specializationAt`
|
|
645
|
+
* answered nothing for it. The callee then read as the generic function's
|
|
646
|
+
* OPEN type: a `generic-function-set` with no closed family for
|
|
647
|
+
* `ir/lower-invocation.ts` to dispatch over. hono's
|
|
648
|
+
* `findMiddleware(middleware[m], path)` inside `RegExpRouter<T>.add`, whose
|
|
649
|
+
* `T` binds to `HandlerWithMetadata<T>` rather than to `T`, is that shape.
|
|
650
|
+
*
|
|
651
|
+
* The reference's own members ARE the images the checker already built for
|
|
652
|
+
* this exact instantiation, so pairing each against the target's is the same
|
|
653
|
+
* lockstep walk, reading members instead of parameters.
|
|
654
|
+
*
|
|
655
|
+
* The open side comes from the TARGET, never from the member's declaration:
|
|
656
|
+
* an inherited member's declaration spells the BASE's parameter, while the
|
|
657
|
+
* body that reads it spells the derived class's, and those are different
|
|
658
|
+
* type objects. `Hono<E, S, BasePath>.router` is `HonoBase`'s field seen
|
|
659
|
+
* through `Hono`'s own parameters, and that is what the constructor writes.
|
|
660
|
+
*
|
|
661
|
+
* Only a source-declared CLASS is walked. Interfaces and aliases hold no
|
|
662
|
+
* bodies, so no site inside one can need a filling, and a lib class
|
|
663
|
+
* (`Map<string, number>`) would cost a full member resolution to answer for
|
|
664
|
+
* a body this compilation never walks.
|
|
665
|
+
*/
|
|
666
|
+
/**
|
|
667
|
+
* `containsHole`, followed through call and construct SIGNATURES.
|
|
668
|
+
*
|
|
669
|
+
* `containsHole` reads a type's own type arguments and stops: a member whose
|
|
670
|
+
* type is a FUNCTION mentioning the class's parameter -- `add(key: string,
|
|
671
|
+
* value: T): void`, `match: typeof match<Router<T>, T>` -- has no type
|
|
672
|
+
* arguments of its own, so it read as closed and `memberFillingsOf` skipped
|
|
673
|
+
* it. The composite pairs those members are the only source of are then
|
|
674
|
+
* missing from the copy, and `filledBy` answers `null` for exactly the hole
|
|
675
|
+
* the fixpoint needed: hono's `RegExpRouter<T>` never minted the copy of
|
|
676
|
+
* `match` its own field initializer names, and emission refused the read as a
|
|
677
|
+
* declaration the program never introduces.
|
|
678
|
+
*
|
|
679
|
+
* Used ONLY as the member walk's admission gate, where a wider answer can
|
|
680
|
+
* only add pairs. `containsHole` itself stays as it is: it also gates whether
|
|
681
|
+
* a TUPLE is concrete enough to mint a copy, and widening it there would
|
|
682
|
+
* withhold copies that are minted today.
|
|
683
|
+
*/
|
|
684
|
+
const mentionsHoleThroughSignatures = (type, depth = 0) => {
|
|
685
|
+
if (containsHole(type, depth))
|
|
686
|
+
return true;
|
|
687
|
+
if (depth > 4)
|
|
688
|
+
return false;
|
|
689
|
+
const parameterMentions = (parameter) => {
|
|
690
|
+
const at = parameter.valueDeclaration ?? parameter.declarations?.[0];
|
|
691
|
+
return at !== undefined && mentionsHoleThroughSignatures(checker.getTypeOfSymbolAtLocation(parameter, at), depth + 1);
|
|
692
|
+
};
|
|
693
|
+
for (const signature of [...type.getCallSignatures(), ...type.getConstructSignatures()]) {
|
|
694
|
+
if (mentionsHoleThroughSignatures(signature.getReturnType(), depth + 1))
|
|
695
|
+
return true;
|
|
696
|
+
const receiver = signature.thisParameter;
|
|
697
|
+
if (receiver && parameterMentions(receiver))
|
|
698
|
+
return true;
|
|
699
|
+
if (signature.parameters.some(parameterMentions))
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
return false;
|
|
703
|
+
};
|
|
704
|
+
const memberFillingsOf = (owner, target, reference) => {
|
|
705
|
+
if (!ts.isClassLike(owner) || owner.getSourceFile().isDeclarationFile)
|
|
706
|
+
return null;
|
|
707
|
+
const held = memberFillings.get(reference);
|
|
708
|
+
if (held !== undefined)
|
|
709
|
+
return held;
|
|
710
|
+
const declared = new Map();
|
|
711
|
+
for (const property of checker.getPropertiesOfType(target))
|
|
712
|
+
declared.set(String(property.escapedName), property);
|
|
713
|
+
const pairs = new Map();
|
|
714
|
+
for (const property of checker.getPropertiesOfType(reference)) {
|
|
715
|
+
const open = declared.get(String(property.escapedName));
|
|
716
|
+
if (!open)
|
|
717
|
+
continue;
|
|
718
|
+
const openType = checker.getTypeOfSymbol(open);
|
|
719
|
+
if (!mentionsHoleThroughSignatures(openType))
|
|
720
|
+
continue;
|
|
721
|
+
unify(checker, openType, checker.getTypeOfSymbol(property), 0, () => undefined, (composite, closed) => {
|
|
722
|
+
if (!pairs.has(composite))
|
|
723
|
+
pairs.set(composite, closed);
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
const answer = pairs.size > 0 ? pairs : null;
|
|
727
|
+
memberFillings.set(reference, answer);
|
|
728
|
+
return answer;
|
|
729
|
+
};
|
|
730
|
+
/**
|
|
731
|
+
* A type reference the program writes -- or, with `node` null, one it makes
|
|
732
|
+
* without writing (a call's own resolved return type).
|
|
733
|
+
*
|
|
734
|
+
* `node` is what `sites` is keyed by, and only a WRITTEN reference has one to
|
|
735
|
+
* be keyed by. A call node is already the key of the callee's own
|
|
736
|
+
* instantiation (`fromCall`), so re-keying it here would silently replace
|
|
737
|
+
* that entry -- the same collision `fromImplementation` passes `null` to
|
|
738
|
+
* avoid.
|
|
739
|
+
*
|
|
740
|
+
* `spellingOnly` is the other half of that distinction: a written reference
|
|
741
|
+
* is a program STATING an instantiation, and a call's return type is only the
|
|
742
|
+
* checker naming one, which may or may not be a copy the program makes. See
|
|
743
|
+
* `deferredSpellings`.
|
|
744
|
+
*/
|
|
745
|
+
const fromTypeReference = (node, type, spellingOnly = false) => {
|
|
746
|
+
const reference = type;
|
|
747
|
+
const target = reference.target;
|
|
748
|
+
const parameters = target?.typeParameters;
|
|
749
|
+
const args = reference.typeArguments;
|
|
750
|
+
if (!target || !parameters || !args)
|
|
751
|
+
return;
|
|
752
|
+
const owner = ownerOf(parameters[0]?.getSymbol()?.declarations?.[0]);
|
|
753
|
+
if (!owner)
|
|
754
|
+
return;
|
|
755
|
+
const bound = new Map();
|
|
756
|
+
for (let index = 0; index < Math.min(parameters.length, args.length); index += 1) {
|
|
757
|
+
const parameter = parameters[index];
|
|
758
|
+
const filling = args[index];
|
|
759
|
+
const symbol = parameter?.getSymbol();
|
|
760
|
+
if (symbol && filling)
|
|
761
|
+
bound.set(symbol, filling);
|
|
762
|
+
}
|
|
763
|
+
// A reference that is its own target's open self (`Box<T>` written inside
|
|
764
|
+
// `Box`'s own body) closes nothing, and a still-open argument records no
|
|
765
|
+
// copy below at all -- neither is worth a member walk.
|
|
766
|
+
const closes = args.some((argument, index) => argument !== parameters[index]) && !args.some((argument) => containsHole(argument));
|
|
767
|
+
// A bare `TypeReferenceNode` is the one shape here that states no value.
|
|
768
|
+
// The same function also receives the `NewExpression` that constructs one
|
|
769
|
+
// and the `ExpressionWithTypeArguments` of a heritage clause, whose copy
|
|
770
|
+
// every instance of the derived class really does contain.
|
|
771
|
+
const constructs = node === null || !ts.isTypeReferenceNode(node);
|
|
772
|
+
recordTuple(owner, bound, node, 0, type, null, spellingOnly, closes ? memberFillingsOf(owner, target, reference) : null, null, constructs);
|
|
773
|
+
};
|
|
774
|
+
/** The expression a call-like node reaches its callee through. */
|
|
775
|
+
const calleeExpressionOf = (node) => ts.isTaggedTemplateExpression(node)
|
|
776
|
+
? node.tag
|
|
777
|
+
: ts.isJsxOpeningLikeElement(node)
|
|
778
|
+
? node.tagName
|
|
779
|
+
: ts.isCallOrNewExpression(node)
|
|
780
|
+
? node.expression
|
|
781
|
+
: null;
|
|
782
|
+
/**
|
|
783
|
+
* The uninstantiated signature a call was resolved from.
|
|
784
|
+
*
|
|
785
|
+
* `Signature.target` is where the checker keeps this and it is not public
|
|
786
|
+
* API, so the generic is recovered the way a reader would: from the callee's
|
|
787
|
+
* own type. A callee whose type carries exactly one signature and that
|
|
788
|
+
* signature declares type parameters is the generic this call instantiated.
|
|
789
|
+
*
|
|
790
|
+
* An OVERLOAD SET is recovered by declaration identity instead of being
|
|
791
|
+
* skipped. An instantiated signature keeps the declaration of the overload
|
|
792
|
+
* it came from, so the overload the checker selected is the one member of
|
|
793
|
+
* the set that was declared at the same node -- a fact the checker states,
|
|
794
|
+
* not a guess from argument position. Skipping the whole set instead is what
|
|
795
|
+
* left hono's `c.json({ hello: 'world' })` recording no instantiation at
|
|
796
|
+
* all: `JSONRespond` declares two generic call signatures, so the call that
|
|
797
|
+
* every hono program makes bound nothing.
|
|
798
|
+
*/
|
|
799
|
+
const genericSignatureOf = (node, resolved) => {
|
|
800
|
+
const callee = calleeExpressionOf(node);
|
|
801
|
+
if (!callee)
|
|
802
|
+
return null;
|
|
803
|
+
const type = checker.getTypeAtLocation(callee);
|
|
804
|
+
const signatures = ts.isNewExpression(node) ? type.getConstructSignatures() : type.getCallSignatures();
|
|
805
|
+
const declaration = resolved?.getDeclaration();
|
|
806
|
+
const selected = signatures.find((signature) => declaration !== undefined && signature.getDeclaration() === declaration) ??
|
|
807
|
+
(signatures.length === 1 ? signatures[0] : undefined);
|
|
808
|
+
if (!selected)
|
|
809
|
+
return null;
|
|
810
|
+
return selected.getTypeParameters()?.length ? selected : null;
|
|
811
|
+
};
|
|
812
|
+
/**
|
|
813
|
+
* The generic FUNCTION that implements the declared generic signature a call
|
|
814
|
+
* resolved to, when the two are different declarations.
|
|
815
|
+
*
|
|
816
|
+
* `json: JSONRespond = <T, U>(object: T, ...) => ...` (hono's `Context`)
|
|
817
|
+
* writes the signature twice: once as the field's declared type, which is
|
|
818
|
+
* what every call site resolves against, and once as the arrow that provides
|
|
819
|
+
* the body. Only the first is reachable from the call, so the arrow was
|
|
820
|
+
* `isGeneric` with zero copies -- and `census.ts` walks such a declaration
|
|
821
|
+
* NOT AT ALL. The field initializer then had no operations, and its body
|
|
822
|
+
* emitted `return;` from a function whose convention returns a callable:
|
|
823
|
+
* every hono program's `c.json` was an uninitialized field, invisible until
|
|
824
|
+
* clang rejected the return.
|
|
825
|
+
*
|
|
826
|
+
* The mapping is POSITIONAL, which is what "this function implements that
|
|
827
|
+
* signature" means -- TypeScript's own assignability check for a
|
|
828
|
+
* generic-to-generic assignment relates the parameters in order, and it has
|
|
829
|
+
* already accepted this program. A count that disagrees is not a mapping
|
|
830
|
+
* this can guess, so it records nothing.
|
|
831
|
+
*/
|
|
832
|
+
const implementationOfCallee = (node) => {
|
|
833
|
+
const callee = calleeExpressionOf(node);
|
|
834
|
+
if (!callee)
|
|
835
|
+
return null;
|
|
836
|
+
const value = checker.getSymbolAtLocation(callee)?.valueDeclaration;
|
|
837
|
+
if (!value || !(ts.isPropertyDeclaration(value) || ts.isVariableDeclaration(value)) || !value.initializer)
|
|
838
|
+
return null;
|
|
839
|
+
const initializer = value.initializer;
|
|
840
|
+
if (!ts.isFunctionLike(initializer))
|
|
841
|
+
return null;
|
|
842
|
+
return typeParametersOf(initializer).length > 0 ? initializer : null;
|
|
843
|
+
};
|
|
844
|
+
/** Record the implementation's own copy of an instantiation recorded for the signature it implements. */
|
|
845
|
+
const fromImplementation = (node, declaredOwner, bound) => {
|
|
846
|
+
const implementation = implementationOfCallee(node);
|
|
847
|
+
if (!implementation || implementation === declaredOwner)
|
|
848
|
+
return;
|
|
849
|
+
const declared = typeParametersOf(declaredOwner);
|
|
850
|
+
const implemented = typeParametersOf(implementation);
|
|
851
|
+
if (declared.length !== implemented.length)
|
|
852
|
+
return;
|
|
853
|
+
const mapped = new Map();
|
|
854
|
+
for (let index = 0; index < declared.length; index += 1) {
|
|
855
|
+
const from = declared[index];
|
|
856
|
+
const to = implemented[index];
|
|
857
|
+
const filling = from ? bound.get(checker.getSymbolAtLocation(from.name)) : undefined;
|
|
858
|
+
const symbol = to ? checker.getSymbolAtLocation(to.name) : undefined;
|
|
859
|
+
if (!filling || !symbol)
|
|
860
|
+
return;
|
|
861
|
+
mapped.set(symbol, filling);
|
|
862
|
+
}
|
|
863
|
+
// `at` is deliberately `null`: the call site already maps to the DECLARED
|
|
864
|
+
// signature's instantiation, and a second entry for the same node would
|
|
865
|
+
// silently replace it. Nothing resolves a name to the implementation
|
|
866
|
+
// through the call -- the field's own carrier is what the call reaches.
|
|
867
|
+
recordTuple(implementation, mapped, null);
|
|
868
|
+
};
|
|
869
|
+
/**
|
|
870
|
+
* The declaration whose BODY a call resolved against, when the signature
|
|
871
|
+
* the checker selected is one of an overload set's declared overloads.
|
|
872
|
+
*
|
|
873
|
+
* A call to `some(xs)` resolves to the first of `some`'s two signature-only
|
|
874
|
+
* declarations, so its `getDeclaration()` is a node with no body -- and a
|
|
875
|
+
* copy minted on that node is a copy of nothing: `census.ts` walks only
|
|
876
|
+
* declarations with bodies, so the implementation stayed "generic with no
|
|
877
|
+
* copies", walked not at all, while every call named an ordinal the body
|
|
878
|
+
* never had. TypeScript's own `core.ts` writes `some`, `find`, `every`,
|
|
879
|
+
* `filter`, `map` and `findIndex` this way, and together they were the
|
|
880
|
+
* largest families still reaching representation with a naked type
|
|
881
|
+
* parameter after namespaces became paths.
|
|
882
|
+
*
|
|
883
|
+
* The implementation is the one runtime function
|
|
884
|
+
* (FunctionDeclarationInstantiation runs once for the whole set, and
|
|
885
|
+
* `identities.ts`'s `valueDeclarationOfSymbol` already names it for every
|
|
886
|
+
* read), so it is the one declaration copies can belong to. The fillings
|
|
887
|
+
* are recovered by unifying the implementation's OWN signature against the
|
|
888
|
+
* resolved one: the resolved overload's parameters are the implementation's
|
|
889
|
+
* in order (TypeScript has already checked the implementation is compatible
|
|
890
|
+
* with each overload), so the implementation's `T` binds where the
|
|
891
|
+
* overload's did.
|
|
892
|
+
*/
|
|
893
|
+
const implementationOf = (declaration) => {
|
|
894
|
+
if (!(ts.isFunctionDeclaration(declaration) || ts.isMethodDeclaration(declaration)) || declaration.body !== undefined)
|
|
895
|
+
return declaration;
|
|
896
|
+
const name = ts.getNameOfDeclaration(declaration);
|
|
897
|
+
const symbol = name ? checker.getSymbolAtLocation(name) : undefined;
|
|
898
|
+
const implementation = symbol
|
|
899
|
+
?.getDeclarations()
|
|
900
|
+
?.find((candidate) => (ts.isFunctionDeclaration(candidate) || ts.isMethodDeclaration(candidate)) && candidate.body !== undefined);
|
|
901
|
+
return implementation ?? declaration;
|
|
902
|
+
};
|
|
903
|
+
/**
|
|
904
|
+
* The generic source functions a call's callee is a CHOICE among, or `null`.
|
|
905
|
+
*
|
|
906
|
+
* `setOriginal(updated, original)` where `const setOriginal = cond ?
|
|
907
|
+
* identity : setOriginalNode`: the callee's type is a union of two open
|
|
908
|
+
* generic function types, and the checker resolved the call to a signature
|
|
909
|
+
* it combined from both. Neither member is the callee; the cell holds one
|
|
910
|
+
* of them, decided at runtime, and every member must have the copy this
|
|
911
|
+
* call instantiates. The same predicate `structural.ts`'s
|
|
912
|
+
* `genericSourceFunctionOf` states for the VALUE's shape, asked here of the
|
|
913
|
+
* call: module-level function declarations with a body, at least two.
|
|
914
|
+
*/
|
|
915
|
+
const genericSetMembersOf = (node) => ts.isCallExpression(node) ? genericFunctionChoiceMembersOf(checker, node.expression) : null;
|
|
916
|
+
const fromCall = (node) => {
|
|
917
|
+
const resolved = checker.getResolvedSignature(node);
|
|
918
|
+
const setMembers = resolved ? genericSetMembersOf(node) : null;
|
|
919
|
+
if (resolved && setMembers) {
|
|
920
|
+
// Every member unifies its OWN signature against the one signature the
|
|
921
|
+
// checker resolved the call to: the combined signature's parameters are
|
|
922
|
+
// each member's, positionally (TypeScript's `combineUnionParameters`),
|
|
923
|
+
// so the fillings each member binds are the ones this call supplies.
|
|
924
|
+
const recorded = [];
|
|
925
|
+
for (const member of setMembers) {
|
|
926
|
+
const open = checker.getSignatureFromDeclaration(member);
|
|
927
|
+
if (!open)
|
|
928
|
+
continue;
|
|
929
|
+
const bound = new Map();
|
|
930
|
+
const pairs = new Map();
|
|
931
|
+
unifySignatures(checker, [open], [resolved], 0, (parameter, filling) => {
|
|
932
|
+
const symbol = parameter.getSymbol();
|
|
933
|
+
if (symbol && !bound.has(symbol))
|
|
934
|
+
bound.set(symbol, filling);
|
|
935
|
+
}, (composite, closed) => {
|
|
936
|
+
if (!pairs.has(composite))
|
|
937
|
+
pairs.set(composite, closed);
|
|
938
|
+
});
|
|
939
|
+
recordTuple(member, bound, null, 0, null, null, false, pairs, (tuple) => recorded.push({ declaration: member, fillings: tuple }));
|
|
940
|
+
}
|
|
941
|
+
// A member whose tuple this call does not bind is a member with no copy
|
|
942
|
+
// here, and a dispatch missing one arm is not a dispatch: the site is
|
|
943
|
+
// recorded only when every member has one.
|
|
944
|
+
if (recorded.length === setMembers.length)
|
|
945
|
+
setSites.set(node, recorded);
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const generic = genericSignatureOf(node, resolved);
|
|
949
|
+
if (!generic || !resolved || generic === resolved)
|
|
950
|
+
return;
|
|
951
|
+
const declared = generic.getDeclaration();
|
|
952
|
+
if (!declared)
|
|
953
|
+
return;
|
|
954
|
+
const owner = implementationOf(declared);
|
|
955
|
+
let open = generic;
|
|
956
|
+
if (owner !== declared) {
|
|
957
|
+
const implementation = checker.getSignatureFromDeclaration(owner);
|
|
958
|
+
// An implementation with no type parameters of its own is one function
|
|
959
|
+
// however many generic overloads it answers for: nothing to mint.
|
|
960
|
+
if (!implementation || (implementation.getTypeParameters()?.length ?? 0) === 0)
|
|
961
|
+
return;
|
|
962
|
+
open = implementation;
|
|
963
|
+
}
|
|
964
|
+
const bound = new Map();
|
|
965
|
+
const pairs = new Map();
|
|
966
|
+
unifySignatures(checker, [open], [resolved], 0, (parameter, filling) => {
|
|
967
|
+
const symbol = parameter.getSymbol();
|
|
968
|
+
if (symbol && !bound.has(symbol))
|
|
969
|
+
bound.set(symbol, filling);
|
|
970
|
+
}, (composite, closed) => {
|
|
971
|
+
if (!pairs.has(composite))
|
|
972
|
+
pairs.set(composite, closed);
|
|
973
|
+
});
|
|
974
|
+
// No signature pair for a copy minted through an overload: the resolved
|
|
975
|
+
// signature is the OVERLOAD's frame instantiated, not the implementation's
|
|
976
|
+
// -- `some<T>(array, predicate?)` resolved through `some(array, predicate)`
|
|
977
|
+
// pairs the optional parameter with a required one, and
|
|
978
|
+
// `structural-instantiated-member.ts` would read that pair back as the
|
|
979
|
+
// copy's parameter type, dropping the optionality the body relies on. The
|
|
980
|
+
// tuple binds the implementation's `T` exactly, and that is the whole of
|
|
981
|
+
// what such a copy needs.
|
|
982
|
+
recordTuple(owner, bound, node, 0, null, owner === declared ? [open, resolved] : null, false, pairs);
|
|
983
|
+
// A call's resolved return type can name an instantiation the program
|
|
984
|
+
// makes, already spelled by the checker -- and that spelling is the one
|
|
985
|
+
// thing `structural-instantiated-member.ts` needs to read a copy's members
|
|
986
|
+
// with the hole closed.
|
|
987
|
+
//
|
|
988
|
+
// Without this, a generic returned by a generic FUNCTION gets its copy
|
|
989
|
+
// minted by the fixpoint round below, which substitutes the fillings into
|
|
990
|
+
// the site and records them with no image at all: `Collection@4`
|
|
991
|
+
// (`tuple=[DataKey]`, from `db.collection<DataKey>(...)` in
|
|
992
|
+
// `client_encryption.ts`) was the only one of the mongodb probe's five
|
|
993
|
+
// `Collection` copies without one, and every `AlternativeType` still
|
|
994
|
+
// deferred on that probe -- 43 of 452 mandatory obligations, the largest
|
|
995
|
+
// single root -- was in that copy. The four minted from a written
|
|
996
|
+
// `Collection<X>` annotation carried an image and resolved.
|
|
997
|
+
//
|
|
998
|
+
// SPELLING ONLY, and that distinction is the whole of it. A return type is
|
|
999
|
+
// the checker naming an instantiation, not the program stating one, and a
|
|
1000
|
+
// method on a generic class names its own class back (`Hono.get` returns
|
|
1001
|
+
// `Hono<E, S, MergePath<...>, ...>`) -- so minting from it manufactures a
|
|
1002
|
+
// copy per call site that nothing instantiates. That regressed hono from
|
|
1003
|
+
// certified to six unmet obligations: three class-property arrows whose
|
|
1004
|
+
// carriers only exist in the copies the program really makes. The spelling
|
|
1005
|
+
// waits in `deferredSpellings` for a site that mints, which is what the
|
|
1006
|
+
// mongodb case needs anyway: `Collection@4` is minted by the fixpoint round
|
|
1007
|
+
// BELOW this, so a back-fill that only wrote to existing ordinals would
|
|
1008
|
+
// have answered nothing there either.
|
|
1009
|
+
fromTypeReference(null, resolved.getReturnType(), true);
|
|
1010
|
+
fromImplementation(node, owner, bound);
|
|
1011
|
+
};
|
|
1012
|
+
/**
|
|
1013
|
+
* A generic callable's type parameters filled with their CONSTRAINTS -- the
|
|
1014
|
+
* one instantiation a generic used as a VALUE can have.
|
|
1015
|
+
*
|
|
1016
|
+
* `memoizeOne(<T extends JSDocType>(kind: T["kind"]) => ...)` (TypeScript's
|
|
1017
|
+
* `nodeFactory.ts`) passes a generic arrow to a higher-order function. No
|
|
1018
|
+
* call fills that arrow's `T`: the checker propagates it into
|
|
1019
|
+
* `memoizeOne`'s result (`<T extends JSDocType>(arg: T["kind"]) => ...`),
|
|
1020
|
+
* and a later call through that result infers `T` from an argument that
|
|
1021
|
+
* cannot name it and lands on the constraint. The value is ONE closure at
|
|
1022
|
+
* runtime, so it cannot be one body per instantiation the way a called
|
|
1023
|
+
* generic is; it can only be the body every instantiation shares, which is
|
|
1024
|
+
* the body over the constraints. `structural.ts` gives an unbound
|
|
1025
|
+
* callable-owned parameter the same answer, so the copy and every mention
|
|
1026
|
+
* of the value's type agree.
|
|
1027
|
+
*
|
|
1028
|
+
* A constraint that still names a hole (`Children extends NodeArray<Child>`)
|
|
1029
|
+
* is no filling: `null`, and the value stays honestly uninstantiated.
|
|
1030
|
+
*/
|
|
1031
|
+
const constraintBindingsOf = (declaration) => {
|
|
1032
|
+
const bound = new Map();
|
|
1033
|
+
for (const parameter of typeParametersOf(declaration)) {
|
|
1034
|
+
const symbol = checker.getSymbolAtLocation(parameter.name);
|
|
1035
|
+
if (!symbol)
|
|
1036
|
+
return null;
|
|
1037
|
+
const constraint = checker.getBaseConstraintOfType(checker.getDeclaredTypeOfSymbol(symbol)) ?? checker.getUnknownType();
|
|
1038
|
+
if (containsHole(constraint))
|
|
1039
|
+
return null;
|
|
1040
|
+
bound.set(symbol, constraint);
|
|
1041
|
+
}
|
|
1042
|
+
return bound;
|
|
1043
|
+
};
|
|
1044
|
+
/**
|
|
1045
|
+
* The generic source callable a VALUE position denotes, or `null` when the
|
|
1046
|
+
* position is not a value use of one.
|
|
1047
|
+
*
|
|
1048
|
+
* A callee is not a value use -- `fromCall` fills its hole from the call.
|
|
1049
|
+
* Neither is an arm of a generic-function CHOICE (`cond ? identity :
|
|
1050
|
+
* setOriginalNode`): that binding is a set dispatched per call
|
|
1051
|
+
* (`genericSetMembersOf`), and a constraint copy minted for each arm would be
|
|
1052
|
+
* a second, unrelated copy the set's own sites never name.
|
|
1053
|
+
*/
|
|
1054
|
+
const valueUseSubjectOf = (node) => {
|
|
1055
|
+
const parent = node.parent;
|
|
1056
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
1057
|
+
// A binding, field or literal property INITIALIZED with a generic arrow
|
|
1058
|
+
// is the arrow named: its copies come from the calls made through that
|
|
1059
|
+
// name (`genericSubjectOf`, `implementationOfCallee`), one per
|
|
1060
|
+
// instantiation. A constraint copy minted here as well was the one the
|
|
1061
|
+
// initializer then cited -- measured: `respond: Respond = <T extends
|
|
1062
|
+
// object>(value: T) => ...` handed `box.respond({ hello })` a closure
|
|
1063
|
+
// over `{}` and the call refused the conversion to its own copy.
|
|
1064
|
+
if ((ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertyAssignment(parent)) &&
|
|
1065
|
+
parent.initializer === node) {
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1068
|
+
return typeParametersOf(node).length > 0 ? node : null;
|
|
1069
|
+
}
|
|
1070
|
+
// A namespace-qualified name is the REFERENCE, not a property read:
|
|
1071
|
+
// `namespace-paths.ts` is the one authority that says so, and the whole
|
|
1072
|
+
// `State.enter` access is what denotes the declaration -- exactly what a
|
|
1073
|
+
// bare `enter` written inside the namespace body would denote. Without
|
|
1074
|
+
// this the value use was never recorded, the name kept the generic's OPEN
|
|
1075
|
+
// type, and `representation/derive.ts` carried it as a
|
|
1076
|
+
// `generic-function-set` tag in a position whose cell holds a callable:
|
|
1077
|
+
// `test/runtime/generic-state-function-array.ts` refused the conversion
|
|
1078
|
+
// from the tag to `function-value-dispatch`, while the same program
|
|
1079
|
+
// written with bare identifiers compiled and ran.
|
|
1080
|
+
const qualifiedMember = ts.isPropertyAccessExpression(node) ? namespacePaths.memberSymbolOf(node) : null;
|
|
1081
|
+
if (!ts.isIdentifier(node) && qualifiedMember === null)
|
|
1082
|
+
return null;
|
|
1083
|
+
if ((ts.isCallExpression(parent) || ts.isNewExpression(parent) || ts.isTaggedTemplateExpression(parent)) &&
|
|
1084
|
+
calleeExpressionOf(parent) === node)
|
|
1085
|
+
return null;
|
|
1086
|
+
// `const alias = doubler` is an ALIAS of the generic, not a value made from
|
|
1087
|
+
// it: `genericSubjectOf` hops the alias to its target so the alias's own
|
|
1088
|
+
// calls mint the target's copies. A constraint copy minted here instead
|
|
1089
|
+
// read the alias as one closure over `unknown` -- measured: `alias(7)`
|
|
1090
|
+
// refused `function-value-dispatch((dynamic) -> array-object(dynamic))
|
|
1091
|
+
// -> function-value-dispatch((scalar(number)) -> array-object(number))`.
|
|
1092
|
+
if (ts.isVariableDeclaration(parent) && parent.initializer === node && parent.type === undefined)
|
|
1093
|
+
return null;
|
|
1094
|
+
if (parent.name === node && !ts.isPropertyAccessExpression(parent))
|
|
1095
|
+
return null;
|
|
1096
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === node)
|
|
1097
|
+
return null;
|
|
1098
|
+
if (ts.isExportSpecifier(parent) || ts.isImportSpecifier(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent))
|
|
1099
|
+
return null;
|
|
1100
|
+
if (ts.isTypeOfExpression(parent) || ts.isDecorator(parent) || ts.isJsxOpeningLikeElement(parent) || ts.isJsxClosingElement(parent))
|
|
1101
|
+
return null;
|
|
1102
|
+
for (let ancestor = parent; ancestor !== undefined; ancestor = ancestor.parent) {
|
|
1103
|
+
if (ts.isTypeNode(ancestor) || ts.isTypeQueryNode(ancestor))
|
|
1104
|
+
return null;
|
|
1105
|
+
if (ts.isStatement(ancestor) || ts.isSourceFile(ancestor))
|
|
1106
|
+
break;
|
|
1107
|
+
}
|
|
1108
|
+
let top = node;
|
|
1109
|
+
while (top.parent !== undefined &&
|
|
1110
|
+
(ts.isParenthesizedExpression(top.parent) ||
|
|
1111
|
+
ts.isConditionalExpression(top.parent) ||
|
|
1112
|
+
ts.isAsExpression(top.parent) ||
|
|
1113
|
+
ts.isNonNullExpression(top.parent) ||
|
|
1114
|
+
ts.isSatisfiesExpression(top.parent) ||
|
|
1115
|
+
(ts.isBinaryExpression(top.parent) &&
|
|
1116
|
+
(top.parent.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
|
|
1117
|
+
top.parent.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken)))) {
|
|
1118
|
+
top = top.parent;
|
|
1119
|
+
}
|
|
1120
|
+
if (genericFunctionChoiceMembersOf(checker, top))
|
|
1121
|
+
return null;
|
|
1122
|
+
let symbol = qualifiedMember ?? checker.getSymbolAtLocation(node);
|
|
1123
|
+
if (symbol && (symbol.flags & ts.SymbolFlags.Alias) !== 0)
|
|
1124
|
+
symbol = checker.getAliasedSymbol(symbol);
|
|
1125
|
+
const value = symbol?.valueDeclaration;
|
|
1126
|
+
if (!value || value.getSourceFile().isDeclarationFile)
|
|
1127
|
+
return null;
|
|
1128
|
+
if (ts.isFunctionDeclaration(value)) {
|
|
1129
|
+
const implementation = implementationOf(value);
|
|
1130
|
+
return ts.isFunctionDeclaration(implementation) && implementation.body !== undefined && typeParametersOf(implementation).length > 0
|
|
1131
|
+
? implementation
|
|
1132
|
+
: null;
|
|
1133
|
+
}
|
|
1134
|
+
if (ts.isVariableDeclaration(value) && value.initializer !== undefined && ts.isFunctionLike(value.initializer)) {
|
|
1135
|
+
const initializer = value.initializer;
|
|
1136
|
+
return typeParametersOf(initializer).length > 0 ? initializer : null;
|
|
1137
|
+
}
|
|
1138
|
+
return null;
|
|
1139
|
+
};
|
|
1140
|
+
/**
|
|
1141
|
+
* A generic callable used as a VALUE rather than called: the copy that
|
|
1142
|
+
* value is.
|
|
1143
|
+
*
|
|
1144
|
+
* Two cases, told apart by what the checker did at the use. When the
|
|
1145
|
+
* contextual type is a plain signature the checker instantiated the generic
|
|
1146
|
+
* in context -- `binarySearch(array, insert, identity, compare)` reads
|
|
1147
|
+
* `identity` as `(x: T) => T` over the CALLER's `T` -- and that instantiation
|
|
1148
|
+
* is recorded exactly as a call's would be, keyed on this node so
|
|
1149
|
+
* `useSitePath` resolves the name to it. When the type at the use still
|
|
1150
|
+
* carries the callable's own parameters (a generic arrow handed to a
|
|
1151
|
+
* higher-order function, a generic function passed where the parameter's
|
|
1152
|
+
* type is itself generic), nothing instantiated it and the copy is the one
|
|
1153
|
+
* over the constraints (`constraintBindingsOf`).
|
|
1154
|
+
*/
|
|
1155
|
+
const fromValueUse = (node) => {
|
|
1156
|
+
const subject = valueUseSubjectOf(node);
|
|
1157
|
+
if (!subject)
|
|
1158
|
+
return;
|
|
1159
|
+
const open = checker.getSignatureFromDeclaration(subject);
|
|
1160
|
+
if (!open)
|
|
1161
|
+
return;
|
|
1162
|
+
const signatures = checker.getTypeAtLocation(node).getCallSignatures();
|
|
1163
|
+
const instantiated = signatures.length === 1 ? signatures[0] : undefined;
|
|
1164
|
+
if (instantiated && instantiated !== open && (instantiated.getTypeParameters()?.length ?? 0) === 0) {
|
|
1165
|
+
const bound = new Map();
|
|
1166
|
+
const pairs = new Map();
|
|
1167
|
+
unifySignatures(checker, [open], [instantiated], 0, (parameter, filling) => {
|
|
1168
|
+
const symbol = parameter.getSymbol();
|
|
1169
|
+
if (symbol && !bound.has(symbol))
|
|
1170
|
+
bound.set(symbol, filling);
|
|
1171
|
+
}, (composite, closed) => {
|
|
1172
|
+
if (!pairs.has(composite))
|
|
1173
|
+
pairs.set(composite, closed);
|
|
1174
|
+
});
|
|
1175
|
+
recordTuple(subject, bound, node, 0, null, [open, instantiated], false, pairs);
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
// Nothing instantiated it. When the position's CONTEXTUAL type is itself
|
|
1179
|
+
// a generic signature (`emitNodeList(emit, ...)` over `EmitFunction = <T
|
|
1180
|
+
// extends Node>(node: T, ...) => void`), the value's parameters unify with
|
|
1181
|
+
// that type's own -- holes a function type owns -- and the fixpoint below
|
|
1182
|
+
// fills them from the instantiation the program makes of that type
|
|
1183
|
+
// (`fromCall` records one per call through a value of it): the cell then
|
|
1184
|
+
// holds a copy of `emit` over exactly the `T` its reads are typed with.
|
|
1185
|
+
// A type instantiated more than one way, or never, leaves the site open
|
|
1186
|
+
// and `closeOpenValueUses` mints the constraint copy instead.
|
|
1187
|
+
const contextual = checker.getContextualType(node);
|
|
1188
|
+
const contextualSignatures = contextual?.getCallSignatures() ?? [];
|
|
1189
|
+
const contextualSignature = contextualSignatures.length === 1 ? contextualSignatures[0] : undefined;
|
|
1190
|
+
// A generic handed to a PARAMETER DEFAULT is left open by the checker even
|
|
1191
|
+
// though the position states exactly one signature: `same: Same<T> =
|
|
1192
|
+
// equateValues` reads `equateValues` as its own `<T>(a: T, b: T) => boolean`
|
|
1193
|
+
// with `Same<T>` only as the contextual type. The same value written into an
|
|
1194
|
+
// annotated binding in the body IS instantiated, so the first branch catches
|
|
1195
|
+
// that one and this position fell through to the constraint copy -- a closure
|
|
1196
|
+
// over `unknown` that no copy of the enclosing generic could then accept.
|
|
1197
|
+
//
|
|
1198
|
+
// The contextual signature here owns no parameters of its own: every hole in
|
|
1199
|
+
// it belongs to the ENCLOSING generic, which is exactly the filling
|
|
1200
|
+
// `recordTuple` records without minting (`sites`), for the enclosing copy to
|
|
1201
|
+
// substitute when it reads the site back. This is tsc's `contains`,
|
|
1202
|
+
// `binarySearch` and `sortAndDeduplicate` family, whose defaulted
|
|
1203
|
+
// `EqualityComparer<T>`/`Comparer<T>` parameters are the largest single root
|
|
1204
|
+
// in its self-compile.
|
|
1205
|
+
if (contextualSignature && (contextualSignature.getTypeParameters()?.length ?? 0) === 0 && contextualSignature !== open) {
|
|
1206
|
+
const bound = new Map();
|
|
1207
|
+
const pairs = new Map();
|
|
1208
|
+
unifySignatures(checker, [open], [contextualSignature], 0, (parameter, filling) => {
|
|
1209
|
+
const symbol = parameter.getSymbol();
|
|
1210
|
+
if (symbol && !bound.has(symbol))
|
|
1211
|
+
bound.set(symbol, filling);
|
|
1212
|
+
}, (composite, closed) => {
|
|
1213
|
+
if (!pairs.has(composite))
|
|
1214
|
+
pairs.set(composite, closed);
|
|
1215
|
+
});
|
|
1216
|
+
if (bound.size === typeParametersOf(subject).length) {
|
|
1217
|
+
recordTuple(subject, bound, node, 0, null, [open, contextualSignature], false, pairs);
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
if (contextualSignature && (contextualSignature.getTypeParameters()?.length ?? 0) > 0) {
|
|
1222
|
+
const bound = new Map();
|
|
1223
|
+
const pairs = new Map();
|
|
1224
|
+
unifySignatures(checker, [open], [contextualSignature], 0, (parameter, filling) => {
|
|
1225
|
+
const symbol = parameter.getSymbol();
|
|
1226
|
+
if (symbol && !bound.has(symbol))
|
|
1227
|
+
bound.set(symbol, filling);
|
|
1228
|
+
}, (composite, closed) => {
|
|
1229
|
+
if (!pairs.has(composite))
|
|
1230
|
+
pairs.set(composite, closed);
|
|
1231
|
+
});
|
|
1232
|
+
if (bound.size === typeParametersOf(subject).length) {
|
|
1233
|
+
recordTuple(subject, bound, node, 0, null, null, false, pairs);
|
|
1234
|
+
return;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
// A generic referenced as a VALUE inside its OWN body denotes the copy that
|
|
1238
|
+
// is running -- recursion names itself. tsc's `Debug` family is written
|
|
1239
|
+
// this way throughout: `checkDefined` hands `stackCrawlMark ||
|
|
1240
|
+
// checkDefined` to `assertIsDefined`, which hands `stackCrawlMark ||
|
|
1241
|
+
// assertIsDefined` to `fail`. Answering the constraint copy there made
|
|
1242
|
+
// every copy's own read refuse the conversion from a closure over
|
|
1243
|
+
// `unknown` to its own frame -- 265 rows in `debug.ts`, the largest
|
|
1244
|
+
// single-file root in tsc's self-compile.
|
|
1245
|
+
//
|
|
1246
|
+
// The fillings are the enclosing generic's OWN parameters, so the site
|
|
1247
|
+
// stays open and `specializationAt` substitutes it per copy exactly as
|
|
1248
|
+
// any other enclosing hole (`fillsFromEnclosingCopy`).
|
|
1249
|
+
if (enclosesNode(subject, node)) {
|
|
1250
|
+
const parameters = typeParametersOf(subject);
|
|
1251
|
+
const own = new Map();
|
|
1252
|
+
for (const parameter of parameters) {
|
|
1253
|
+
const symbol = checker.getSymbolAtLocation(parameter.name);
|
|
1254
|
+
if (symbol)
|
|
1255
|
+
own.set(symbol, checker.getDeclaredTypeOfSymbol(symbol));
|
|
1256
|
+
}
|
|
1257
|
+
if (own.size === parameters.length) {
|
|
1258
|
+
recordTuple(subject, own, node);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
const bound = constraintBindingsOf(subject);
|
|
1263
|
+
if (bound)
|
|
1264
|
+
recordTuple(subject, bound, node);
|
|
1265
|
+
};
|
|
1266
|
+
/**
|
|
1267
|
+
* The function TYPES whose parameters a site's fillings still name, each
|
|
1268
|
+
* instantiated exactly one way by the program -- the one case a hole a
|
|
1269
|
+
* type owns has a single answer. See `fromValueUse`.
|
|
1270
|
+
*/
|
|
1271
|
+
const holeOwnerOf = (hole) => ownerOf(hole.getSymbol()?.declarations?.[0]);
|
|
1272
|
+
const uniquelyInstantiatedTypeOwnersOf = (fillings) => {
|
|
1273
|
+
const owners = [];
|
|
1274
|
+
for (const filling of fillings) {
|
|
1275
|
+
if (!isHole(filling))
|
|
1276
|
+
continue;
|
|
1277
|
+
const owner = holeOwnerOf(filling);
|
|
1278
|
+
if (!owner || owners.includes(owner))
|
|
1279
|
+
continue;
|
|
1280
|
+
if (!(ts.isFunctionTypeNode(owner) ||
|
|
1281
|
+
ts.isConstructorTypeNode(owner) ||
|
|
1282
|
+
ts.isCallSignatureDeclaration(owner) ||
|
|
1283
|
+
ts.isConstructSignatureDeclaration(owner)))
|
|
1284
|
+
continue;
|
|
1285
|
+
if ((tuples.get(owner)?.length ?? 0) === 1)
|
|
1286
|
+
owners.push(owner);
|
|
1287
|
+
}
|
|
1288
|
+
return owners;
|
|
1289
|
+
};
|
|
1290
|
+
/** Whether `node` sits inside `declaration` -- the self-reference test in `fromValueUse`. */
|
|
1291
|
+
const enclosesNode = (declaration, node) => {
|
|
1292
|
+
for (let current = node.parent; current !== undefined; current = current.parent)
|
|
1293
|
+
if (current === declaration)
|
|
1294
|
+
return true;
|
|
1295
|
+
return false;
|
|
1296
|
+
};
|
|
1297
|
+
/**
|
|
1298
|
+
* Whether every hole in a site's fillings belongs to an enclosing generic
|
|
1299
|
+
* this program instantiates -- the case the read resolves per copy through
|
|
1300
|
+
* `specializationAt`'s `substitute`, rather than one the constraints close.
|
|
1301
|
+
*/
|
|
1302
|
+
const fillsFromEnclosingCopy = (node, fillings) => {
|
|
1303
|
+
const enclosing = enclosingGenericsOf(node);
|
|
1304
|
+
return fillings.every((filling) => {
|
|
1305
|
+
if (!containsHole(filling))
|
|
1306
|
+
return true;
|
|
1307
|
+
if (!isHole(filling))
|
|
1308
|
+
return false;
|
|
1309
|
+
const owner = holeOwnerOf(filling);
|
|
1310
|
+
return owner !== null && enclosing.includes(owner) && (tuples.get(owner)?.length ?? 0) > 0;
|
|
1311
|
+
});
|
|
1312
|
+
};
|
|
1313
|
+
/**
|
|
1314
|
+
* A value use still open after the fixpoint -- its contextual type's holes
|
|
1315
|
+
* had no single instantiation to fill them from -- becomes the copy over
|
|
1316
|
+
* the constraints: one closure, the only thing the value can be.
|
|
1317
|
+
*/
|
|
1318
|
+
const closeOpenValueUses = () => {
|
|
1319
|
+
for (const [node, site] of sites) {
|
|
1320
|
+
if (!(ts.isIdentifier(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node)))
|
|
1321
|
+
continue;
|
|
1322
|
+
if (!ts.isFunctionLike(site.declaration))
|
|
1323
|
+
continue;
|
|
1324
|
+
if (!site.fillings.some((filling) => containsHole(filling)))
|
|
1325
|
+
continue;
|
|
1326
|
+
if (site.fillings.some((filling) => !isHole(filling) && containsHole(filling)))
|
|
1327
|
+
continue;
|
|
1328
|
+
// ⛔ A hole an ENCLOSING generic owns is not an open value use: the
|
|
1329
|
+
// fixpoint above leaves those sites open ON PURPOSE, because there is one
|
|
1330
|
+
// site and one substitution per enclosing copy, made when that copy reads
|
|
1331
|
+
// the site back. Closing them here re-keyed the site to a single closure
|
|
1332
|
+
// over the constraints and threw the per-copy answer away -- measured on
|
|
1333
|
+
// a generic passed as a defaulted parameter (`same: Same<T> =
|
|
1334
|
+
// equateValues`), where every copy of the enclosing function then refused
|
|
1335
|
+
// the conversion from a closure over `any` to its own comparer.
|
|
1336
|
+
if (fillsFromEnclosingCopy(node, site.fillings))
|
|
1337
|
+
continue;
|
|
1338
|
+
const bound = constraintBindingsOf(site.declaration);
|
|
1339
|
+
if (bound)
|
|
1340
|
+
recordTuple(site.declaration, bound, node);
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
const declared = new Set();
|
|
1344
|
+
// Whether a declaration *writes down* type parameters is a property of the
|
|
1345
|
+
// declaration alone, so this half stays whole-program even though the
|
|
1346
|
+
// instantiation half below does not. `isGeneric` is what `census.ts`'s walk
|
|
1347
|
+
// and `producers/declaration-lifecycle.ts`'s `namesUninstantiatedGeneric`
|
|
1348
|
+
// both read to tell "generic with no copies" from "not generic", and
|
|
1349
|
+
// answering the second for a declaration reachability happens not to walk
|
|
1350
|
+
// turns an elided `export * from` into one that mints an operation carried
|
|
1351
|
+
// by the open hole. Measured, before this was split out: four
|
|
1352
|
+
// `unresolved-reaches-materialization` violations in each of seven corpus
|
|
1353
|
+
// programs, every one an export of a generic that program never calls.
|
|
1354
|
+
const declareVisit = (node) => {
|
|
1355
|
+
if (typeParametersOf(node).length > 0)
|
|
1356
|
+
declared.add(node);
|
|
1357
|
+
ts.forEachChild(node, declareVisit);
|
|
1358
|
+
};
|
|
1359
|
+
for (const file of sourceFiles)
|
|
1360
|
+
declareVisit(file);
|
|
1361
|
+
const visit = (node) => {
|
|
1362
|
+
// A PRUNED member is a site this compilation does not reach either, and
|
|
1363
|
+
// statement-level reachability cannot say so: a dead method lives inside a
|
|
1364
|
+
// live class declaration, so `forEachChild` walks straight into it.
|
|
1365
|
+
//
|
|
1366
|
+
// `mongodb-connection-string-url`'s `typedSearchParams<T extends
|
|
1367
|
+
// Record<string, any>>()` is the case, and it is the shape to expect:
|
|
1368
|
+
// its body is the type-only trick `(false as true) && new
|
|
1369
|
+
// (caseInsenstiveURLSearchParams<keyof T & string>(URLSearchParams))()`,
|
|
1370
|
+
// written to name a type and never to run. Nothing spells the method, so
|
|
1371
|
+
// reachability prunes it -- and this walk minted copies of a LIVE generic
|
|
1372
|
+
// from it anyway, filled with `keyof T & string` for a `T` that, having no
|
|
1373
|
+
// call site, no copy and no default, can never be closed. Every method of
|
|
1374
|
+
// those copies then carried an unresolved intersection: 56 of the mongodb
|
|
1375
|
+
// probe's 516 mandatory obligations, all from one method nothing calls.
|
|
1376
|
+
if (reachable.memberIsPruned(node))
|
|
1377
|
+
return;
|
|
1378
|
+
if (ts.isCallOrNewExpression(node) || ts.isTaggedTemplateExpression(node) || ts.isJsxOpeningLikeElement(node))
|
|
1379
|
+
fromCall(node);
|
|
1380
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isIdentifier(node) || ts.isPropertyAccessExpression(node))
|
|
1381
|
+
fromValueUse(node);
|
|
1382
|
+
if (ts.isExpressionWithTypeArguments(node) || ts.isTypeReferenceNode(node) || ts.isNewExpression(node)) {
|
|
1383
|
+
fromTypeReference(node, checker.getTypeAtLocation(node));
|
|
1384
|
+
}
|
|
1385
|
+
ts.forEachChild(node, visit);
|
|
1386
|
+
};
|
|
1387
|
+
// An instantiation, unlike a declaration, is a *use*: a call site this
|
|
1388
|
+
// compilation does not reach fills no hole in anything.
|
|
1389
|
+
for (const file of sourceFiles)
|
|
1390
|
+
for (const statement of reachable.statementsOf(file))
|
|
1391
|
+
visit(statement);
|
|
1392
|
+
/**
|
|
1393
|
+
* The generic declarations a node is written INSIDE, innermost first --
|
|
1394
|
+
* exactly the scopes whose copies can fill a hole this node spells.
|
|
1395
|
+
*/
|
|
1396
|
+
const enclosingGenericsOf = (node) => {
|
|
1397
|
+
const owners = [];
|
|
1398
|
+
for (let current = node.parent; current !== undefined; current = current.parent) {
|
|
1399
|
+
if (declared.has(current))
|
|
1400
|
+
owners.push(current);
|
|
1401
|
+
}
|
|
1402
|
+
return owners;
|
|
1403
|
+
};
|
|
1404
|
+
/**
|
|
1405
|
+
* What one copy of an enclosing generic fills a site's argument with, or
|
|
1406
|
+
* `null` when it fills nothing this can act on.
|
|
1407
|
+
*
|
|
1408
|
+
* Only a filling that IS a hole the copy itself binds is substituted -- the
|
|
1409
|
+
* same limit `induceFromHeritage` states, for the same reason. A hole nested
|
|
1410
|
+
* inside an argument (`inner<Wrapper<T>>`) would need a type instantiated,
|
|
1411
|
+
* which the public checker API does not offer, so it stays honestly
|
|
1412
|
+
* uninstantiated rather than becoming a guess.
|
|
1413
|
+
*/
|
|
1414
|
+
const filledBy = (filling, owner, tuple) => {
|
|
1415
|
+
if (!containsHole(filling))
|
|
1416
|
+
return filling;
|
|
1417
|
+
if (!isHole(filling)) {
|
|
1418
|
+
// `inner(items)` with `items: T[]` inside `outer<T>`: the hole is inside
|
|
1419
|
+
// the argument, and only the checker can build `string[]` -- which it
|
|
1420
|
+
// already did, for the call that minted this copy of `outer`, in the
|
|
1421
|
+
// resolved signature `fillingOf` reads. A copy with no call behind it
|
|
1422
|
+
// answers nothing and the site stays honestly uninstantiated.
|
|
1423
|
+
const ordinal = ordinalOfArguments(owner, tuple);
|
|
1424
|
+
const image = ordinal === null ? undefined : compositeFillings.get(owner)?.[ordinal]?.get(filling);
|
|
1425
|
+
return image !== undefined && !containsHole(image) ? image : null;
|
|
1426
|
+
}
|
|
1427
|
+
const parameter = filling.getSymbol()?.declarations?.[0];
|
|
1428
|
+
if (!parameter || !ts.isTypeParameterDeclaration(parameter))
|
|
1429
|
+
return null;
|
|
1430
|
+
const index = typeParametersOf(owner).indexOf(parameter);
|
|
1431
|
+
const bound = index >= 0 ? tuple[index] : undefined;
|
|
1432
|
+
return bound !== undefined && !containsHole(bound) ? bound : null;
|
|
1433
|
+
};
|
|
1434
|
+
/**
|
|
1435
|
+
* Close the enumeration under SUBSTITUTION, not just under what one source
|
|
1436
|
+
* line spells out.
|
|
1437
|
+
*
|
|
1438
|
+
* `outer<T>(op: T) { inner(op) }` instantiates `inner` once per copy of
|
|
1439
|
+
* `outer`, but the syntactic walk sees the site written with a HOLE and
|
|
1440
|
+
* records no tuple for it -- so `inner` had no copies, `census.ts` walked its
|
|
1441
|
+
* body not at all, and the call's callee carried a signature over a naked
|
|
1442
|
+
* type parameter that `derive.ts` correctly refuses. Answering "no copies"
|
|
1443
|
+
* there is not conservative, it is wrong, for the identical reason
|
|
1444
|
+
* `induceFromHeritage` states about a base class: this is that same closure
|
|
1445
|
+
* for a CALL rather than a heritage clause, and the two exist because
|
|
1446
|
+
* enumeration has to be closed under what a recorded copy induces.
|
|
1447
|
+
*
|
|
1448
|
+
* Repeated to a fixed point because the induction chains: `a` calls `b`
|
|
1449
|
+
* calls `c`, and `c`'s copies only become minteable once `b` has some. It
|
|
1450
|
+
* terminates because a substitution can only ever produce a tuple built from
|
|
1451
|
+
* types some copy ALREADY binds, so the reachable set is finite; the round
|
|
1452
|
+
* cap is a fail-safe against a future substitution rule that grows a type
|
|
1453
|
+
* rather than replacing one, never the thing that makes this stop.
|
|
1454
|
+
*/
|
|
1455
|
+
const openSites = function* () {
|
|
1456
|
+
yield* sites;
|
|
1457
|
+
for (const [node, members] of setSites)
|
|
1458
|
+
for (const site of members)
|
|
1459
|
+
yield [node, site];
|
|
1460
|
+
};
|
|
1461
|
+
for (let round = 0; round < 8; round += 1) {
|
|
1462
|
+
let minted = false;
|
|
1463
|
+
for (const [node, site] of openSites()) {
|
|
1464
|
+
if (!site.fillings.some((filling) => containsHole(filling)))
|
|
1465
|
+
continue;
|
|
1466
|
+
const parameters = typeParametersOf(site.declaration);
|
|
1467
|
+
// A value use whose holes a uniquely instantiated function TYPE owns
|
|
1468
|
+
// has ONE answer, so the site itself is re-keyed to it (`at` is the
|
|
1469
|
+
// node): the reference then resolves to that copy through
|
|
1470
|
+
// `specializationAt` exactly as a call's does. An enclosing generic's
|
|
1471
|
+
// holes are the other way round -- one site, one substitution per
|
|
1472
|
+
// enclosing copy -- and those sites stay open below on purpose.
|
|
1473
|
+
const typeOwners = uniquelyInstantiatedTypeOwnersOf(site.fillings);
|
|
1474
|
+
if (typeOwners.length > 0) {
|
|
1475
|
+
let fillings = site.fillings;
|
|
1476
|
+
for (const owner of typeOwners) {
|
|
1477
|
+
const tuple = tuples.get(owner)?.[0];
|
|
1478
|
+
if (!tuple)
|
|
1479
|
+
continue;
|
|
1480
|
+
fillings = fillings.map((filling) => filling !== null && isHole(filling) && holeOwnerOf(filling) === owner ? filledBy(filling, owner, tuple) : filling);
|
|
1481
|
+
}
|
|
1482
|
+
if (fillings.length === parameters.length && !fillings.some((filling) => filling === null || containsHole(filling))) {
|
|
1483
|
+
const bound = new Map();
|
|
1484
|
+
parameters.forEach((parameter, index) => {
|
|
1485
|
+
const symbol = checker.getSymbolAtLocation(parameter.name);
|
|
1486
|
+
const filling = fillings[index];
|
|
1487
|
+
if (symbol && filling)
|
|
1488
|
+
bound.set(symbol, filling);
|
|
1489
|
+
});
|
|
1490
|
+
const existing = ordinalOfArguments(site.declaration, fillings);
|
|
1491
|
+
const fresh = existing === null;
|
|
1492
|
+
if (existing !== null)
|
|
1493
|
+
markConstructed(site.declaration, existing);
|
|
1494
|
+
recordTuple(site.declaration, bound, node);
|
|
1495
|
+
if (fresh)
|
|
1496
|
+
minted = true;
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
for (const owner of enclosingGenericsOf(node)) {
|
|
1501
|
+
for (const tuple of tuples.get(owner) ?? []) {
|
|
1502
|
+
const substituted = site.fillings.map((filling) => filledBy(filling, owner, tuple));
|
|
1503
|
+
if (substituted.length !== parameters.length || substituted.some((filling) => filling === null))
|
|
1504
|
+
continue;
|
|
1505
|
+
const already = ordinalOfArguments(site.declaration, substituted);
|
|
1506
|
+
if (already !== null) {
|
|
1507
|
+
markConstructed(site.declaration, already);
|
|
1508
|
+
continue;
|
|
1509
|
+
}
|
|
1510
|
+
const bound = new Map();
|
|
1511
|
+
parameters.forEach((parameter, index) => {
|
|
1512
|
+
const symbol = checker.getSymbolAtLocation(parameter.name);
|
|
1513
|
+
const filling = substituted[index];
|
|
1514
|
+
if (symbol && filling)
|
|
1515
|
+
bound.set(symbol, filling);
|
|
1516
|
+
});
|
|
1517
|
+
// Through `recordTuple` rather than `tupleOrdinal` so a class copy
|
|
1518
|
+
// minted here induces its own heritage exactly as a syntactic one
|
|
1519
|
+
// does; `at` is null because the SITE is already recorded, with the
|
|
1520
|
+
// holes its own copy substitutes when it reads them back.
|
|
1521
|
+
recordTuple(site.declaration, bound, null);
|
|
1522
|
+
minted = true;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (!minted)
|
|
1527
|
+
break;
|
|
1528
|
+
}
|
|
1529
|
+
closeOpenValueUses();
|
|
1530
|
+
const built = new Map();
|
|
1531
|
+
// Every declaration that *writes down* type parameters is one this census
|
|
1532
|
+
// specializes, including the ones the program instantiates none. "Generic
|
|
1533
|
+
// with no copies" and "not generic" are different answers, and only the first
|
|
1534
|
+
// one lets the census walk decide to walk a body not at all: a generic whose
|
|
1535
|
+
// hole nothing fills has no meaning to walk, exactly as a C++ template nobody
|
|
1536
|
+
// instantiates emits nothing. Registering it with an empty list is what makes
|
|
1537
|
+
// `isGeneric` able to say so; `specializationsOf` still answers `[]`, which is
|
|
1538
|
+
// what it answered before.
|
|
1539
|
+
for (const declaration of declared)
|
|
1540
|
+
built.set(declaration, []);
|
|
1541
|
+
for (const [declaration, seen] of tuples) {
|
|
1542
|
+
const parameters = typeParametersOf(declaration);
|
|
1543
|
+
built.set(declaration, seen.map((tuple, ordinal) => ({
|
|
1544
|
+
ordinal,
|
|
1545
|
+
arguments: tuple,
|
|
1546
|
+
instantiated: spellings.get(declaration)?.[ordinal] ?? null,
|
|
1547
|
+
instantiatedSignature: signaturePairs.get(declaration)?.[ordinal] ?? null,
|
|
1548
|
+
bindingOf: (parameter) => {
|
|
1549
|
+
const index = parameters.indexOf(parameter);
|
|
1550
|
+
return index >= 0 ? (tuple[index] ?? null) : null;
|
|
1551
|
+
},
|
|
1552
|
+
fillingOf: (open) => compositeFillings.get(declaration)?.[ordinal]?.get(open) ?? null
|
|
1553
|
+
})));
|
|
1554
|
+
}
|
|
1555
|
+
/** Whether the program mints this copy at all, rather than only naming it. See `constructions`. */
|
|
1556
|
+
const isConstructed = (declaration, ordinal) => constructions.get(declaration)?.[ordinal] ?? true;
|
|
1557
|
+
const copiesMayDiffer = new Map();
|
|
1558
|
+
const canonicalFillings = new Map();
|
|
1559
|
+
/**
|
|
1560
|
+
* The copy a site of a NON-splitting class resolves to: its canonical one.
|
|
1561
|
+
*
|
|
1562
|
+
* Canonicalising only the instance ANCHOR leaves the class one struct with
|
|
1563
|
+
* several method copies, and a body still typed at the wider filling then
|
|
1564
|
+
* reads the canonical field and refuses -- `ReadableStream`'s `any` copy
|
|
1565
|
+
* reading a `typed-array` `queue_`. One layout is one set of bodies, so a
|
|
1566
|
+
* class that must not split resolves every site to the same copy.
|
|
1567
|
+
*/
|
|
1568
|
+
const canonicalOrdinalOf = (declaration, ordinal) => {
|
|
1569
|
+
const canonical = census.canonicalLayoutFillings(declaration);
|
|
1570
|
+
if (canonical === null)
|
|
1571
|
+
return ordinal;
|
|
1572
|
+
const copies = built.get(declaration) ?? [];
|
|
1573
|
+
const found = copies.find((copy) => copy.arguments.length === canonical.length && copy.arguments.every((one, index) => one === canonical[index]));
|
|
1574
|
+
return found?.ordinal ?? ordinal;
|
|
1575
|
+
};
|
|
1576
|
+
const census = {
|
|
1577
|
+
// A class that must not split has ONE layout, so every copy of it is
|
|
1578
|
+
// typed at the canonical fillings. Without this the wider copy keeps its
|
|
1579
|
+
// own bodies, and those read the canonical field and refuse -- the
|
|
1580
|
+
// `unknown` copy of `ReadableStream` reading a `typed-array` `queue_`.
|
|
1581
|
+
//
|
|
1582
|
+
// The copies are REWRITTEN, not dropped. A copy is also what induces the
|
|
1583
|
+
// instantiations its body reaches, so deleting one deletes those: folding
|
|
1584
|
+
// `Context`'s `[any, any, {}]` away took `new HonoRequest(...)` with it,
|
|
1585
|
+
// and `HonoRequest` -- never instantiated anywhere else with closed
|
|
1586
|
+
// fillings -- stopped being censused at all, leaving a class the program
|
|
1587
|
+
// constructs with no constructor object.
|
|
1588
|
+
specializationsOf: (declaration) => {
|
|
1589
|
+
const copies = built.get(declaration) ?? [];
|
|
1590
|
+
const canonical = copies.length < 2 ? null : census.canonicalLayoutFillings(declaration);
|
|
1591
|
+
if (canonical === null)
|
|
1592
|
+
return copies;
|
|
1593
|
+
const chosen = copies.find((copy) => copy.arguments.length === canonical.length && copy.arguments.every((one, index) => one === canonical[index]));
|
|
1594
|
+
if (chosen === undefined)
|
|
1595
|
+
return copies;
|
|
1596
|
+
// The canonical copy WHOLE, not just its `arguments`: a member's type is
|
|
1597
|
+
// read off `instantiated`, and its parameters substitute through
|
|
1598
|
+
// `fillingOf`, so rewriting the argument list alone left the wider
|
|
1599
|
+
// copy's bodies exactly as they were.
|
|
1600
|
+
//
|
|
1601
|
+
// Each copy keeps its own ORDINAL. Collapsing those onto the canonical
|
|
1602
|
+
// one lowered the same body twice and the IR builder threw ("block ...
|
|
1603
|
+
// is already terminated by a branch operation"); dropping the entries
|
|
1604
|
+
// instead left `HonoRequest` never censused and so with no constructor
|
|
1605
|
+
// object to build. One entry per instantiation, all naming one layout.
|
|
1606
|
+
return copies.map((copy) => (copy === chosen ? copy : { ...chosen, ordinal: copy.ordinal }));
|
|
1607
|
+
},
|
|
1608
|
+
isGeneric: (declaration) => built.has(declaration),
|
|
1609
|
+
specializationOfInstance: (type, substitute) => {
|
|
1610
|
+
const symbol = type.getSymbol();
|
|
1611
|
+
const declaration = symbol?.declarations?.find((one) => ts.isClassLike(one) || ts.isInterfaceDeclaration(one));
|
|
1612
|
+
if (!declaration || !built.has(declaration))
|
|
1613
|
+
return null;
|
|
1614
|
+
const parameters = typeParametersOf(declaration);
|
|
1615
|
+
if (parameters.length === 0)
|
|
1616
|
+
return null;
|
|
1617
|
+
const written = (checker.getTypeArguments(type) ?? []).slice(0, parameters.length);
|
|
1618
|
+
if (written.length !== parameters.length)
|
|
1619
|
+
return null;
|
|
1620
|
+
const resolved = substitute ? written.map(substitute) : written;
|
|
1621
|
+
if (resolved.some((filling) => containsHole(filling)))
|
|
1622
|
+
return null;
|
|
1623
|
+
const ordinal = ordinalOfArguments(declaration, resolved);
|
|
1624
|
+
return ordinal === null ? null : { declaration, ordinal: canonicalOrdinalOf(declaration, ordinal) };
|
|
1625
|
+
},
|
|
1626
|
+
copiesMayDifferInLayout: (declaration) => {
|
|
1627
|
+
const known = copiesMayDiffer.get(declaration);
|
|
1628
|
+
if (known !== undefined)
|
|
1629
|
+
return known;
|
|
1630
|
+
const answer = (() => {
|
|
1631
|
+
if (!ts.isClassLike(declaration) || isAmbientDeclaration(declaration))
|
|
1632
|
+
return false;
|
|
1633
|
+
const copies = built.get(declaration) ?? [];
|
|
1634
|
+
const [first, ...rest] = copies;
|
|
1635
|
+
if (first === undefined || rest.length === 0)
|
|
1636
|
+
return false;
|
|
1637
|
+
const layoutRelevant = layoutRelevantParameterIndices(checker, declaration);
|
|
1638
|
+
const fillings = [first, ...rest].map((copy) => copy.arguments.filter((_, index) => layoutRelevant.has(index)));
|
|
1639
|
+
const sameFillings = (left, right) => left.length === right.length && left.every((one, index) => one === right[index]);
|
|
1640
|
+
if (fillings.every((right) => sameFillings(fillings[0] ?? [], right)))
|
|
1641
|
+
return false;
|
|
1642
|
+
// Two copies may be separate STRUCTS only if the program can never put
|
|
1643
|
+
// one where the other is declared. TypeScript's own assignability is
|
|
1644
|
+
// that question: `Token<number>` is assignable to `Token<unknown>`, so
|
|
1645
|
+
// `new Sink(new Token<number>())` against a parameter typed
|
|
1646
|
+
// `string | Token<unknown> | null` is legal TypeScript that must keep
|
|
1647
|
+
// working -- and it cannot if the two copies are different C++ types
|
|
1648
|
+
// with no conversion between them. Measured: splitting them compiled
|
|
1649
|
+
// and then aborted at runtime with "a dynamic value admitted by no
|
|
1650
|
+
// union arm" (`stated-open-union-preserves-closed-arms.ts`). So a
|
|
1651
|
+
// class with ANY pair of assignment-compatible copies keeps its one
|
|
1652
|
+
// shared layout, exactly as before copies could split at all --
|
|
1653
|
+
// `number` and `string` flow into each other in neither direction, so
|
|
1654
|
+
// `Box<number>` and `Box<string>` still split.
|
|
1655
|
+
// A position the class keeps in MUTABLE storage cannot be shared. The
|
|
1656
|
+
// assignability shortcut below exists so copies the program passes
|
|
1657
|
+
// into each other keep one layout, but it cannot apply here: one
|
|
1658
|
+
// struct would store one copy's field type while the other copy still
|
|
1659
|
+
// writes its own, which is a runtime abort rather than a refusal.
|
|
1660
|
+
// `ReadableStream<R>`'s `private queue_: R[]`, held at `unknown` and
|
|
1661
|
+
// at `Uint8Array`, is the measured case -- these really are two
|
|
1662
|
+
// layouts, and the deriver keys them apart on their representations.
|
|
1663
|
+
const stored = parametersInInstanceStorage(checker, declaration);
|
|
1664
|
+
// Indexed against each copy's FULL argument list: `fillings` above is
|
|
1665
|
+
// already filtered down to the relevant positions.
|
|
1666
|
+
// A difference involving `any` does NOT force the split. `any` is
|
|
1667
|
+
// TypeScript's UNCHECKED top: a program that writes it has already
|
|
1668
|
+
// opted out of the guarantee, and hono's `Context` -- held at
|
|
1669
|
+
// `[any, any, {}]` and `[BlankEnv, any, {}]` -- is passed between
|
|
1670
|
+
// those copies on exactly that licence. `unknown` is the CHECKED top
|
|
1671
|
+
// and carries no such licence, so `ReadableStream<unknown>` beside
|
|
1672
|
+
// `ReadableStream<Uint8Array>` still splits, which is the pair whose
|
|
1673
|
+
// fold aborted at runtime.
|
|
1674
|
+
// Only copies the program MINTS can conflict over a shared field: a
|
|
1675
|
+
// copy that exists solely as an annotation holds no value to be
|
|
1676
|
+
// written through it. That is what tells `ReadableStream<unknown>`,
|
|
1677
|
+
// which `TransformStream` really does construct and enqueue into,
|
|
1678
|
+
// apart from the `Token<unknown>` arm of a union that only ever
|
|
1679
|
+
// receives a `Token<number>`.
|
|
1680
|
+
const written = copies.filter((copy) => isConstructed(declaration, copy.ordinal)).map((copy) => copy.arguments);
|
|
1681
|
+
if ([...layoutRelevant]
|
|
1682
|
+
.filter((index) => stored.has(index))
|
|
1683
|
+
.some((index) => written.some((left) => written.some((right) => left[index] !== right[index] && !openFilling(left[index]) && !openFilling(right[index])))))
|
|
1684
|
+
return true;
|
|
1685
|
+
const flowsInto = (source, target) => source.length === target.length &&
|
|
1686
|
+
source.every((one, index) => {
|
|
1687
|
+
const other = target[index];
|
|
1688
|
+
return other !== undefined && (one === other || checker.isTypeAssignableTo(one, other));
|
|
1689
|
+
});
|
|
1690
|
+
for (let index = 0; index < fillings.length; index += 1)
|
|
1691
|
+
for (let other = index + 1; other < fillings.length; other += 1) {
|
|
1692
|
+
const left = fillings[index] ?? [];
|
|
1693
|
+
const right = fillings[other] ?? [];
|
|
1694
|
+
if (sameFillings(left, right))
|
|
1695
|
+
continue;
|
|
1696
|
+
if (flowsInto(left, right) || flowsInto(right, left))
|
|
1697
|
+
return false;
|
|
1698
|
+
}
|
|
1699
|
+
return true;
|
|
1700
|
+
})();
|
|
1701
|
+
copiesMayDiffer.set(declaration, answer);
|
|
1702
|
+
return answer;
|
|
1703
|
+
},
|
|
1704
|
+
canonicalLayoutFillings: (declaration) => {
|
|
1705
|
+
const known = canonicalFillings.get(declaration);
|
|
1706
|
+
if (known !== undefined)
|
|
1707
|
+
return known;
|
|
1708
|
+
canonicalFillings.set(declaration, null);
|
|
1709
|
+
const answer = (() => {
|
|
1710
|
+
if (!ts.isClassLike(declaration) || isAmbientDeclaration(declaration))
|
|
1711
|
+
return null;
|
|
1712
|
+
// Only a class that must NOT split has one shared struct to name.
|
|
1713
|
+
if (census.copiesMayDifferInLayout(declaration))
|
|
1714
|
+
return null;
|
|
1715
|
+
const copies = built.get(declaration) ?? [];
|
|
1716
|
+
if (copies.length < 2)
|
|
1717
|
+
return null;
|
|
1718
|
+
const layoutRelevant = layoutRelevantParameterIndices(checker, declaration);
|
|
1719
|
+
if (layoutRelevant.size === 0)
|
|
1720
|
+
return null;
|
|
1721
|
+
// Full argument lists, so a caller can index them with the written
|
|
1722
|
+
// ordinal; only the layout-relevant positions are compared.
|
|
1723
|
+
const fillings = copies.map((copy) => copy.arguments);
|
|
1724
|
+
const minted = copies.map((copy) => isConstructed(declaration, copy.ordinal));
|
|
1725
|
+
const first = fillings[0];
|
|
1726
|
+
if (first === undefined)
|
|
1727
|
+
return null;
|
|
1728
|
+
const relevant = (list) => list.filter((_, index) => layoutRelevant.has(index));
|
|
1729
|
+
const sameFillings = (left, right) => left.length === right.length && left.every((one, index) => one === right[index]);
|
|
1730
|
+
if (fillings.every((right) => sameFillings(relevant(first), relevant(right))))
|
|
1731
|
+
return null;
|
|
1732
|
+
// The most specific copy is the one assignable TO every other, index
|
|
1733
|
+
// by index: `Uint8Array` into `any`, `number` into `unknown`. Reads in
|
|
1734
|
+
// the wider copies then widen out of the struct, which is licensed.
|
|
1735
|
+
//
|
|
1736
|
+
// A copy is folded away only where it is a TOP type. `any` and
|
|
1737
|
+
// `unknown` are not layouts, they are the absence of one: both carry
|
|
1738
|
+
// the `dynamic(declared-any-never-narrowed)` representation, which is
|
|
1739
|
+
// the carrier that cannot share a struct with a concrete one. Every
|
|
1740
|
+
// other difference is a real layout question and is left to the
|
|
1741
|
+
// deriver, which groups copies on their fillings' representations.
|
|
1742
|
+
//
|
|
1743
|
+
// Measured on hono, whose entire build has six classes with more than
|
|
1744
|
+
// one copy:
|
|
1745
|
+
// ReadableStream 0:[unknown] 1,2:[Uint8Array]
|
|
1746
|
+
// Context 0:[any, any, {}] 1:[BlankEnv, any, {}]
|
|
1747
|
+
// HonoRequest 0:["/", {}] 1:[any, I["out"]]
|
|
1748
|
+
// The first two fold onto their concrete copy. `HonoRequest` has no
|
|
1749
|
+
// candidate -- copy 1 differs at a position where copy 0 is NOT top --
|
|
1750
|
+
// so it keeps what it had. Restricting this to `any` alone left
|
|
1751
|
+
// `ReadableStream` broken; widening it to plain assignability folded
|
|
1752
|
+
// `Chain<number>` onto `Chain<3>`, which are both concrete, agree on
|
|
1753
|
+
// representation, and each need their own method bodies -- that cost
|
|
1754
|
+
// `generic-method-under-a-later-class-copy.ts` its emission.
|
|
1755
|
+
const topType = (type) => type !== undefined && ((type.flags & ts.TypeFlags.Unknown) !== 0 || openFilling(type));
|
|
1756
|
+
// Two copies can spell one type as two checker objects -- hono holds
|
|
1757
|
+
// `ReadableStream<Uint8Array>` twice, through two `ArrayBufferLike`
|
|
1758
|
+
// instantiations -- so identity alone found no candidate that
|
|
1759
|
+
// absorbed all three copies. Mutual assignability between two
|
|
1760
|
+
// NON-top types is the same type for layout; it is not the loose
|
|
1761
|
+
// test that folded `Chain<number>` onto `Chain<3>`, because a literal
|
|
1762
|
+
// flows into its widening and not back.
|
|
1763
|
+
const sameType = (one, target) => one === target ||
|
|
1764
|
+
(!topType(one) && !topType(target) && checker.isTypeAssignableTo(one, target) && checker.isTypeAssignableTo(target, one));
|
|
1765
|
+
const absorbs = (candidate, other) =>
|
|
1766
|
+
// A copy nothing constructs is a VIEW of whatever value reaches it,
|
|
1767
|
+
// so the layout it names is whichever one is really there.
|
|
1768
|
+
minted[fillings.indexOf(other)] === false ||
|
|
1769
|
+
[...layoutRelevant].every((index) => {
|
|
1770
|
+
const one = candidate[index];
|
|
1771
|
+
const target = other[index];
|
|
1772
|
+
if (one === undefined || target === undefined)
|
|
1773
|
+
return false;
|
|
1774
|
+
return sameType(one, target) || (topType(target) && !topType(one));
|
|
1775
|
+
});
|
|
1776
|
+
const differs = (candidate) => fillings.some((other) => [...layoutRelevant].some((index) => candidate[index] !== other[index]));
|
|
1777
|
+
// And never at a position the class keeps in MUTABLE storage. Folding
|
|
1778
|
+
// there gives one struct a field typed at the concrete copy while the
|
|
1779
|
+
// wider copy still writes whatever its own filling allows -- measured
|
|
1780
|
+
// as a runtime abort, not a refusal, which is strictly worse than the
|
|
1781
|
+
// refusal it replaces. Those copies are two layouts and split.
|
|
1782
|
+
const stored = parametersInInstanceStorage(checker, declaration);
|
|
1783
|
+
const foldable = (candidate) => ![...layoutRelevant].some((index) => stored.has(index) &&
|
|
1784
|
+
fillings.some((other, at) => minted[at] === true &&
|
|
1785
|
+
other[index] !== candidate[index] &&
|
|
1786
|
+
!openFilling(other[index]) &&
|
|
1787
|
+
!openFilling(candidate[index])));
|
|
1788
|
+
// The chosen layout must be one the program actually builds.
|
|
1789
|
+
return (fillings.find((candidate, at) => minted[at] === true && differs(candidate) && foldable(candidate) && fillings.every((other) => absorbs(candidate, other))) ?? null);
|
|
1790
|
+
})();
|
|
1791
|
+
canonicalFillings.set(declaration, answer);
|
|
1792
|
+
return answer;
|
|
1793
|
+
},
|
|
1794
|
+
specializationAt: (node, substitute) => {
|
|
1795
|
+
const site = sites.get(node);
|
|
1796
|
+
if (!site)
|
|
1797
|
+
return null;
|
|
1798
|
+
const resolved = substitute ? site.fillings.map(substitute) : site.fillings;
|
|
1799
|
+
// A filling still open after the asking copy substituted is a hole this
|
|
1800
|
+
// program never fills at this site, and an unfilled hole names no copy.
|
|
1801
|
+
if (resolved.some((filling) => containsHole(filling)))
|
|
1802
|
+
return null;
|
|
1803
|
+
const ordinal = ordinalOfArguments(site.declaration, resolved);
|
|
1804
|
+
return ordinal === null ? null : { declaration: site.declaration, ordinal: canonicalOrdinalOf(site.declaration, ordinal) };
|
|
1805
|
+
},
|
|
1806
|
+
setSpecializationsAt: (node, substitute) => {
|
|
1807
|
+
const members = setSites.get(node);
|
|
1808
|
+
if (!members)
|
|
1809
|
+
return null;
|
|
1810
|
+
const copies = [];
|
|
1811
|
+
for (const site of members) {
|
|
1812
|
+
const resolved = substitute ? site.fillings.map(substitute) : site.fillings;
|
|
1813
|
+
if (resolved.some((filling) => containsHole(filling)))
|
|
1814
|
+
return null;
|
|
1815
|
+
const ordinal = ordinalOfArguments(site.declaration, resolved);
|
|
1816
|
+
if (ordinal === null)
|
|
1817
|
+
return null;
|
|
1818
|
+
copies.push({ declaration: site.declaration, ordinal: canonicalOrdinalOf(site.declaration, ordinal) });
|
|
1819
|
+
}
|
|
1820
|
+
return copies;
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
return census;
|
|
1824
|
+
};
|