From: "hsbt (Hiroshi SHIBATA) via ruby-core" Date: 2026-09-18T00:15:54+00:00 Subject: [ruby-core:126763] [Ruby Bug#22331] Ruby::Box: a box's top self lacks the top-level definition methods Issue #22331 has been reported by hsbt (Hiroshi SHIBATA). ---------------------------------------- Bug #22331: Ruby::Box: a box's top self lacks the top-level definition methods https://bugs.ruby-lang.org/issues/22331 * Author: hsbt (Hiroshi SHIBATA) * Status: Open * Assignee: tagomoris (Satoshi Tagomori) * ruby -v: ruby 4.1.0dev (2026-09-17T00:01:17Z master 3f6143715a) [arm64-darwin27] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Under `RUBY_BOX=1`, loading a file into a box fails on `private`, `public`, `include`, `using`, `define_method` and `ruby2_keywords`. ```ruby # toplevel.rb private def hidden; end puts "loaded" ``` ``` $ RUBY_BOX=1 ruby -W:no-experimental -e 'Ruby::Box.new.load(File.expand_path("toplevel.rb"))' toplevel.rb:1:in '': undefined method 'private' for # (NoMethodError) $ RUBY_BOX=1 ruby -W:no-experimental -e 'load(File.expand_path("toplevel.rb"), true)' toplevel.rb:1:in '': undefined method 'private' for # (NoMethodError) ``` Without a box the same wrapped load only warns. Asking the loaded file what it has shows the difference: ``` $ ruby -e 'load(File.expand_path("show.rb"), true)' [:define_method, :include, :private, :public, :ruby2_keywords, :using] $ RUBY_BOX=1 ruby -W:no-experimental -e 'Ruby::Box.new.load(File.expand_path("show.rb"))' [] ``` The six methods are defined during setup on the singleton class of `rb_vm_top_self()` (`eval.c:2311`, `vm_method.c:3737`, `proc.c:5477`), before the root box exists, so all six land on the master box's top self. `box_entry_initialize()` (`box.c:170`) then gives every other box a fresh object carrying only `to_s` and `inspect`, and `load_wrapping()` (`load.c:848`) clones the current box's one. Top level still sees the master box's object, so the gap shows only from a file loaded into a box. So the question is what a box's top self should be. Three shapes I can see: - give every box a clone of the master box's top self, and let root and main share the master's object itself (https://github.com/ruby/ruby/pull/18707); - define the six methods on each box's own top self when the box is created, the way https://github.com/ruby/ruby/pull/18713 loads the prelude per box; - let every box share the master box's top self, making `main` one object process-wide. They differ in whether a singleton method added to `main` in one box is visible in another. Is there another shape you would prefer? The same identity gap also breaks four autoload specs under a box. Reproduced on master 3f6143715a and on released 4.0.7. Related to #22275 -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/