
Issue #19990 has been updated by fxn (Xavier Noria). @jeremyevans0 We certainly could consider that. Perhaps instead of "protect", the documentation could say what is exactly doing. Like, "pushes the module to the nesting, and changes where top-level methods are defined". This written in a more precise way, perhaps. However, we still have the lack of transparency. Which is the nesting in your program? Well, it is out of your control! How can you program without knowing which is your nesting? That is what the last example shows: ```ruby class A end module X ::A # could be needed if your own lookup had an A somewhere you want to skip end ``` That program would run normally, but fail if loaded with `load program, true`. One way to smooth that out could be: "You cannot load arbitrary code and hope it works. Using this feature needs coordination with the loaded file" (off the top of my head too, wording to be polished). I don't know if that is desirable as a feature, though. What do you think? ---------------------------------------- Bug #19990: Could we reconsider the second argument to Kernel#load? https://bugs.ruby-lang.org/issues/19990#change-105194 * Author: fxn (Xavier Noria) * Status: Open * Priority: Normal * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The documentation of `Kernel#load` says:
If the optional wrap parameter is true, the loaded script will be executed under an anonymous module, protecting the calling program’s global namespace. If the optional wrap parameter is a module, the loaded script will be executed under the given module. In no circumstance will any local variables in the loaded file be propagated to the loading environment.
I'd like to ask you to reconsider this feature. First of all, "protecting the calling program" is not really accomplished because the loaded file may still do this ```ruby class ::C # defines ::C regardless of the second argument end ``` Another example, if the caller defines a module `M`, then the loaded program can also define things in `M`: ```ruby class M::C # defines ::M::C regardless of the second argument end ``` It does not even need a leading `::`. So, the "protection" is not really there. In addition to that, this is not transparent for the code being loaded either. For example, let's take this program: ```ruby class A end module X ::A # could be needed if your own lookup had an A somewhere you want to skip end ``` the Ruby programmer expects that to work. But with this feature, on paper, nobody knows if it wil work. How can you ship code confidently? So, the documentation should say:
It kind of protects, but not really. Also, the loaded file may not work as expected, or may not even be loadable at all.
That hypothetical documentation suggests to me it would be worth revisiting this feature. In Ruby, as it is today, things are global. The language does not have features to really isolate code as containers do, for example. I believe the 2nd argument to `Kernel#load` steers the API in a direction that is not consistent with the language, and provides a feature that is only partial and cannot satisfy what it promises. I'd be in favor of deprecating and eventually removing this API. -- https://bugs.ruby-lang.org/