Skip to content

docs: accuracy sweep + ship reified-T contract + reorganize playground#10

Closed
math3usmartins wants to merge 1 commit into
mainfrom
docs/sweep-and-reified-t
Closed

docs: accuracy sweep + ship reified-T contract + reorganize playground#10
math3usmartins wants to merge 1 commit into
mainfrom
docs/sweep-and-reified-t

Conversation

@math3usmartins

Copy link
Copy Markdown
Member

Three threads landing together after the monorepo restructure merged:

  1. Doc accuracy sweep against actual source.

    Cross-referenced each public README + docs/* against core/src/, tools/lsp/src/, and tools/phpstorm-plugin/src/. Findings + fixes:

    • tools/phpstorm-plugin/README.md: file-type table row was wrong (claimed com.intellij.fileType extension; reality is the plugin deliberately registers no <fileType> and uses a TextMate bundle via XphpBundleRegistrar -- see plugin.xml L93 rationale). Feature table expanded to mirror the full LSP surface enabled by LspCustomization (references, rename, documentSymbol, workspace/symbol). "Semantic tokens" dropped from the wired-up diagram (server doesn't advertise that capability).
    • tools/lsp/README.md: Layout block under-represented the code by ~50%. Added six missing handlers (TextDocument, References, Rename, DocumentSymbol, WorkspaceSymbol, FileWatcher) + FqnIndex
      • nine missing Resolver/ classes (CompletionIndex, CompositeClassLikeLookup, Workspace/FilesystemClassLikeLookup, GenericResolver, GenericParamRegistry, ReferenceFinder, RenameProvider, VarBinding, MethodCallSubstitution, etc.).
    • docs/generics.md: struck "bound checks on method-level type-params aren't enforced yet" -- they ARE, via GenericMethodCompiler -> Registry::checkBounds for both static-call and free-function paths (verified at L344, L402). Added matching note under "Free generic functions".
    • docs/roadmap.md: moved method-level bound validation Next ->
      Shipped > Function-level generics.
    • docs/generics-comparison.md: baseline para rewritten (dropped "post feat/generics-expansion" branch language); Tier 1 add T[] array-type sugar; verify ?T nullable specialization #4 "Already on the MVP-gaps list" replaced with current framing; Cross-language summary moved to the top as the first h2 (quick reference before the per-tier breakdown); bad example fixed -- Box/ with the false "Plastic extends Animal" claim replaced with Box/ (Dog actually extends Animal in playground/src/Models/).
  2. Ship reified-T inside a generic body.

    The Specializer's substituting visitor at core/src/Transpiler/Monomorphize/Specializer.php:146 matches any bare single-segment Name node whose text equals a type-param key -- which is what every new T(...), T::class, T::method(...), instanceof T, T::$prop, and is_a($x, T::class) reduces to syntactically. So all of them are substituted uniformly at codegen, not as special cases. The machinery was fully general; what was missing was fixtures locking the contract so it can't silently regress.

    Added:

    • core/test/fixture/compile/reified_t/ (Reified template + Alpha
      • Beta models + Use site)
    • core/test/Transpiler/Monomorphize/ReifiedTypeParameterIntegrationTest.php (8 tests / 50 assertions: one per substitution form, plus a specialization-independence check, a runtime round-trip via exec(), and a php -l syntax-validity sweep)
    • playground/src/Containers/Reified.xphp + playground/src/Demos/ Reified.xphp (registered in playground/bin/run)

    Core test count: 184 / 495 -> 192 / 545. Docs updated to mark
    reified-T as Shipped (Tier 1 playground #5 retitled with a "shipped" tag,
    cross-language table row simplified, Next opportunities re-numbered;
    roadmap.md Shipped > Runtime semantics gets the new bullet).

  3. Reorganize playground LSP fixtures.

    playground/bin/run had been failing on main because playground/src/Demos/GenericFunction.xphp and playground/src/Demos/Phase3TieBreak.xphp both declared function identity<T> in App\Demos. The Phase3* files are LSP-only fixtures (opened in PhpStorm to verify completion / hover / GTD), not executable demos, and don't belong in Demos/.

    Moved (git mv preserves history):

    • playground/src/Demos/Phase3{BoundAware,ClosedFile, ScopeAwareVars,StaticProp,TieBreak,Utf16}.xphp -> playground/src/LspFixtures/ (namespace App\Demos -> App\LspFixtures)
    • playground/src/Demos/Phase3SubclassProtected.xphp -> playground/src/Models/Wolf.xphp (the class is Wolf extends Animal in namespace App\Models; its prior location under Demos/ violated PSR-4)

    Two latent bugs surfaced once compile succeeded (both had been
    masked by the earlier duplicate-identity bail):

    • LspFixtures/Phase3BoundAware.xphp: type-arg new StringableBox<App\Models\Tag> was namespace-relative-resolved (i.e. App\<current-ns>\App\Models\Tag); changed to short form new StringableBox<Tag> matching the convention in Bounds.xphp.
    • Containers/InMemoryRepository.xphp::items(): new Collection<T>($this->items) was missing the spread operator; Collection(T ...$items) is variadic, so the array tripped a runtime TypeError. Fixed to new Collection<T>(...$this->items).

    playground/README.md tree refreshed to distinguish Demos/
    (executable, in bin/run's list) from LspFixtures/ (editor-only,
    compiled but not run).

Verification:
make -C core test/unit -> 192 tests / 545 assertions
make -C tools/lsp test -> 424 tests / 1244 assertions
playground/bin/run -> executes all 11 demos end-to-end,
including the new Reified demo

Three threads landing together after the monorepo restructure merged:

1. Doc accuracy sweep against actual source.

   Cross-referenced each public README + docs/* against core/src/,
   tools/lsp/src/, and tools/phpstorm-plugin/src/. Findings + fixes:

   - tools/phpstorm-plugin/README.md: file-type table row was wrong
     (claimed `com.intellij.fileType` extension; reality is the plugin
     deliberately registers no `<fileType>` and uses a TextMate bundle
     via XphpBundleRegistrar -- see plugin.xml L93 rationale). Feature
     table expanded to mirror the full LSP surface enabled by
     LspCustomization (references, rename, documentSymbol,
     workspace/symbol). "Semantic tokens" dropped from the wired-up
     diagram (server doesn't advertise that capability).
   - tools/lsp/README.md: Layout block under-represented the code by
     ~50%. Added six missing handlers (TextDocument, References,
     Rename, DocumentSymbol, WorkspaceSymbol, FileWatcher) + FqnIndex
     + nine missing Resolver/ classes (CompletionIndex,
     CompositeClassLikeLookup, Workspace/FilesystemClassLikeLookup,
     GenericResolver, GenericParamRegistry, ReferenceFinder,
     RenameProvider, VarBinding, MethodCallSubstitution, etc.).
   - docs/generics.md: struck "bound checks on method-level type-params
     aren't enforced yet" -- they ARE, via
     GenericMethodCompiler -> Registry::checkBounds for both
     static-call and free-function paths (verified at L344, L402).
     Added matching note under "Free generic functions".
   - docs/roadmap.md: moved method-level bound validation Next ->
     Shipped > Function-level generics.
   - docs/generics-comparison.md: baseline para rewritten (dropped
     "post feat/generics-expansion" branch language); Tier 1 #4
     "Already on the MVP-gaps list" replaced with current framing;
     Cross-language summary moved to the top as the first h2 (quick
     reference before the per-tier breakdown); bad example fixed --
     Box<Plastic>/<Animal> with the false "Plastic extends Animal"
     claim replaced with Box<Dog>/<Animal> (Dog actually extends
     Animal in playground/src/Models/).

2. Ship reified-T inside a generic body.

   The Specializer's substituting visitor at
   core/src/Transpiler/Monomorphize/Specializer.php:146 matches any
   bare single-segment `Name` node whose text equals a type-param key
   -- which is what every `new T(...)`, `T::class`, `T::method(...)`,
   `instanceof T`, `T::$prop`, and `is_a($x, T::class)` reduces to
   syntactically. So all of them are substituted uniformly at codegen,
   not as special cases. The machinery was fully general; what was
   missing was fixtures locking the contract so it can't silently
   regress.

   Added:
   - core/test/fixture/compile/reified_t/ (Reified<T> template + Alpha
     + Beta models + Use site)
   - core/test/Transpiler/Monomorphize/ReifiedTypeParameterIntegrationTest.php
     (8 tests / 50 assertions: one per substitution form, plus a
     specialization-independence check, a runtime round-trip via
     `exec()`, and a `php -l` syntax-validity sweep)
   - playground/src/Containers/Reified.xphp + playground/src/Demos/
     Reified.xphp (registered in playground/bin/run)

   Core test count: 184 / 495 -> 192 / 545. Docs updated to mark
   reified-T as Shipped (Tier 1 #5 retitled with a "shipped" tag,
   cross-language table row simplified, Next opportunities re-numbered;
   roadmap.md Shipped > Runtime semantics gets the new bullet).

3. Reorganize playground LSP fixtures.

   playground/bin/run had been failing on main because
   playground/src/Demos/GenericFunction.xphp and
   playground/src/Demos/Phase3TieBreak.xphp both declared
   `function identity<T>` in `App\Demos`. The Phase3* files are
   LSP-only fixtures (opened in PhpStorm to verify completion / hover
   / GTD), not executable demos, and don't belong in Demos/.

   Moved (git mv preserves history):
   - playground/src/Demos/Phase3{BoundAware,ClosedFile,
     ScopeAwareVars,StaticProp,TieBreak,Utf16}.xphp
     -> playground/src/LspFixtures/
     (namespace `App\Demos` -> `App\LspFixtures`)
   - playground/src/Demos/Phase3SubclassProtected.xphp
     -> playground/src/Models/Wolf.xphp
     (the class is `Wolf extends Animal` in namespace `App\Models`;
     its prior location under Demos/ violated PSR-4)

   Two latent bugs surfaced once compile succeeded (both had been
   masked by the earlier duplicate-identity bail):
   - LspFixtures/Phase3BoundAware.xphp: type-arg
     `new StringableBox<App\Models\Tag>` was namespace-relative-resolved
     (i.e. `App\<current-ns>\App\Models\Tag`); changed to short form
     `new StringableBox<Tag>` matching the convention in Bounds.xphp.
   - Containers/InMemoryRepository.xphp::items():
     `new Collection<T>($this->items)` was missing the spread operator;
     Collection<T>(T ...$items) is variadic, so the array tripped a
     runtime TypeError. Fixed to `new Collection<T>(...$this->items)`.

   playground/README.md tree refreshed to distinguish Demos/
   (executable, in bin/run's list) from LspFixtures/ (editor-only,
   compiled but not run).

Verification:
  make -C core test/unit         -> 192 tests / 545 assertions
  make -C tools/lsp test         -> 424 tests / 1244 assertions
  playground/bin/run             -> executes all 11 demos end-to-end,
                                    including the new Reified demo

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@math3usmartins math3usmartins deleted the docs/sweep-and-reified-t branch May 30, 2026 19:30
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