it's still experimental, so completely fair to have bugs honestly. what i didn't expect was for:
* rack servers like puma to completely choke on missing constants
* the pry console to just completely crash because it doesn't know what Pry is (???)
but this only happened when the Box feature was enabled with the feature flag RUBY_BOX=1.
after a very long and very confusing time had by all, i made a mini ruby installation in a random folder in /tmp and just started putting print statements in source files.
you see, when you run the `pry` executable after installing pry via rubygems or bundler, ruby loads a shebang'd file that essentially does:
#!/path/to/ruby
require "rubygems"
Gem.run_binary_file("pry")
(these are not the real method names, and there's some fiddling about with versions, but this is the gist)
the `require "rubygems"` line is a red herring - it makes it look like the file rubygems.rb, which defines the Gem constant and the method used here, are actually eval'd at runtime.
But it turns out rubygems.rb is evaluated by ruby itself *before any code in the file is run*
*in the root box*.
*not the user box*.
to whit, iff I edit rubygems.rb to add `p Ruby::Box.current` and run a file that just contains
#!/path/to/ruby
raise "lol"
and nothing else, rubygems.rb will happily be evaluated and report that it is in the root box:
#<Ruby::Box:1,root>
anyways, due to the nature of boxes, this means that the entire Gem module from rubygems.rb belongs to the root box. So when bin/pry calls into that method on Gem to load up the *real* executable from the gem, ...
it evaluates the entire gem in the root box also
OOPS
you might not notice this! your app or program may run just fine in the root box! ...unless it does something like pry and rack do, and eval things on TOPLEVEL_BINDING.
which is explicitly a binding on the user box.
which can't see any constants defined by an eval on the root box.
in order for this bug to cause an error, you have to:
* call an executable from a gem, directly and not with `ruby the_file`
* with RUBY_BOX=1
* and that executable must eval text or files in TOPLEVEL_BINDING
* which depend on modules defined in the gem