prevent infinite recursion if a type is seen again
Motivation
The algorithm used to force load all constants is vulnerable to an infinite loop. I hit just such a case when trying to bootstrap sorbet with tapioca in an internal Rails repository at my employer. Running any Tapioca command using this eager load algorithm hung indefinitely after printing that it was loading the Rails application.
I tracked down the issue by vendoring tapioca and adding debug logging statements. The execution continued until Tapioca::Runtime::Trackers::Autoload.eager_load_all! at which point the loop continued indefinitely for the same few constant names.
Implementation
The fix is relatively straightforward: Just maintain a cache of constant names which have already been seen, and skip the processing of a constant name if it was already processed.
Tests
[WIP] I know which internal code is triggering the issue, but still need to generate a test case from it.
Thanks for starting this PR. I am surprised that this code would even enter an infinite loop, since loading a constant that has an autoload registered for it triggers require, which should be idempotent. I tried to create a circular autoload dependency, but could manage to do it.
I would love to see how this can be recreated before attempting to solve the problem.
Yeah, I have no idea why the loop triggered. The code in question is internal code in one of our support gems so I will need to do some work to disentangle the code into a standalone reproduction.