Skip to content

Serve a default gem its stdlib RBS pins when uncached - #85

Draft
apiology wants to merge 1 commit into
masterfrom
fallback-pins-for-default-gems
Draft

Serve a default gem its stdlib RBS pins when uncached#85
apiology wants to merge 1 commit into
masterfrom
fallback-pins-for-default-gems

Conversation

@apiology

@apiology apiology commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Claude:

Problem: DocMap#deserialize_combined_pin_cache builds a gem's RBS pins, holds them in a local variable, and then returns nil without using them.

rbs_map = RbsMap.from_gemspec(gemspec, ...)  # builds the pins - 0.15s for pstore
rbs_version_cache_key = rbs_map.cache_key    # keeps only the string "stdlib"
# no combined/, rbs/ or yard/ entry exists yet, so the method returns nil
# and the pins sitting in rbs_map are discarded

The require resolves to nothing until a separate caching pass rebuilds what was just thrown away. Of 65 stdlib requires probed on Ruby 3.2.6, 43 reach that branch - json, logger, erb, pathname, uri, csv and openssl among them. They ship a gemspec, so DocMap routes them to the cache-file path, while their types live in stdlib RBS, which that path never reads.

Solution: when neither cache file exists, ask the map already in hand for its pins instead of giving up.

The pins are deliberately not stored in combined_pins_in_memory, which is process-wide and would keep serving a provisional set after the real build supersedes it.

No test: the branch is reachable only on a first-ever run in a fresh cache namespace.

🤖 Generated with Claude Code

DocMap#deserialize_combined_pin_cache builds an RbsMap to get a cache
key, then looks for RBS pins in a cache file rather than in the map it
just built. A default gem such as forwardable or logger ships a
gemspec, so it takes that gem path, but its types live in stdlib RBS,
which the path never reads. Nothing writes the file during cataloging,
so the pins are discarded and the gem reads as undocumented until
`solargraph gems` runs.

Where the standard library is what describes the gem, the map in hand
holds those pins, so return them when neither cache file is there.

They are not written to combined_pins_in_memory. That hash is
process-wide and keyed only by gem name and version, so a provisional
set stored there would go on being served for the life of the process,
including after the build that supersedes it.
deserialize_rbs_collection_cache still records the gemspec in
@uncached_rbs_collection_gemspecs, so the deferred build is unchanged.

Extracted from the Forwardable delegation branch, where the gap was
found. It is not specific to forwardable: probing 14 requires on Ruby
3.2.6 found 8 in the same state - forwardable, json, benchmark,
securerandom, logger, delegate, singleton and time.
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