Skip to content

Fix cross-module class indexer -shared gap and add coverage#283

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix/cross-module-class-indexer-shared-gap
Jul 22, 2026
Merged

Fix cross-module class indexer -shared gap and add coverage#283
ASDAlexander77 merged 1 commit into
mainfrom
fix/cross-module-class-indexer-shared-gap

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

  • The super-index-access-gap-fix memory predicted that adding cross-module coverage for class indexers would reproduce the same 2-bug shape PR Fix cross-module -shared get/set accessor resolution gap #281 fixed for accessors. It did.
  • Bug 1 (printer gap): DeclarationPrinter::print(ClassInfo::TypePtr) never re-emitted a class's index signature ([x: T]: U;) when reprinting a -shared @dllimport declaration, so a reimporting module's ClassInfo::indexes stayed empty and obj[i]/super[i] failed with Class member '.index' can't be found. Added printIndexer.
  • Bug 2 (missing dynamic-import fallback): ClassIndexAccess had no isDynamicImport branch (unlike ClassMethodAccess/ClassAccessorAccess), so AOT -shared linking tried to statically resolve the indexer's get/set symbols against an import library -shared mode never links, failing with an undefined-symbol linker error. Routed through the already-existing (but previously unused) ThisIndirectIndexAccessorOp, mirroring ClassAccessorAccess's resolver pattern.

Test plan

  • New export_class_indexer.ts / import_class_indexer.ts cross-module pair, 3 tiers: test-compile-export-import-class-indexer, test-compile-shared-export-import-class-indexer, test-jit-shared-export-import-class-indexer
  • Full suite: ctest -C Debug -j8 — 796/796 green (793 previously green + 3 new)

🤖 Generated with Claude Code

super-index-access-gap-fix.md predicted that adding cross-module
coverage for class indexers would reproduce the exact 2-bug shape
PR #281 fixed for accessors. It did:

1. DeclarationPrinter never re-emitted a class's index signature
   ([x: T]: U;) when reprinting a -shared @dllimport declaration,
   so a reimporting module's ClassInfo::indexes stayed empty and
   `obj[i]`/`super[i]` failed with "Class member '.index' can't be
   found".

2. ClassIndexAccess had no isDynamicImport fallback (unlike
   ClassMethodAccess/ClassAccessorAccess), so AOT -shared linking
   tried to statically resolve the indexer's get/set symbols
   against an import library that -shared mode never links,
   failing with "undefined symbol ... dllimport". Routed through
   the already-existing (but previously unused)
   ThisIndirectIndexAccessorOp instead, mirroring
   ClassAccessorAccess's resolveAccessorFunc pattern.

New export_class_indexer.ts/import_class_indexer.ts cross-module
test pair (compile, -shared compile, -jit -shared tiers). 796/796
green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 44761ad into main Jul 22, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix/cross-module-class-indexer-shared-gap branch July 22, 2026 22:55
ASDAlexander77 added a commit that referenced this pull request Jul 22, 2026
cross-module-class-indexer-shared-gap-fix.md flagged interfaces as
likely sharing the same latent DeclarationPrinter gap as classes did
for index signatures, untested because no cross-module
interface-indexer test existed. It did:

DeclarationPrinter::print(InterfaceInfo::TypePtr) never re-emitted an
interface's index signature ([x: T]: U;) for -shared reimport, so a
reimporting module's InterfaceInfo::indexes stayed empty and casting
to the interface then indexing it failed with "indexer is not
declared" / "Interface member '.index' can't be found".

Printing it uncovered a second, narrower bug: an interface's index
signature FunctionType carries a leading opaque `this` input (added
via getInterfaceMethodNameAndType's funcGenContext.thisType, unlike a
class's plain (arg)->result index signature), so naively reusing
input(0) as the index-argument type printed the wrong type and
crashed an unrelated assert in getIndexSignatureArgumentAndResultTypes
on reimport. Fixed by picking input(1) when the signature has more
than one input, matching that helper's own "first parameter is
Opaque" branch.

Unlike the class case (PR #283), no isDynamicImport fallback was
needed here - interface method dispatch (including the indexer's
synthesized get/set) already goes through vtable slots rather than
statically-linked symbols, so AOT -shared linking was never an issue
once the printer emitted the signature.

New export_interface_indexer.ts/import_interface_indexer.ts
cross-module test pair (compile, -shared compile, -jit -shared
tiers). 799/799 green.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant