Bug #19726
closedScript loaded twice when requiring self
Description
The executed program is not added to $LOADED_FEATURES
unexpectedly resulting in the program possibly being loaded twice:
a.rb:
#!/usr/bin/env ruby
require "./b"
C = 42
return unless __FILE__ == $0
puts C
b.rb:
require "./a"
This results in:
$ ./a.rb
./a.rb:5: warning: already initialized constant C
/home/johannes/t/a.rb:5: warning: previous definition of C was here
42
Ruby version:
$ sudo docker run ruby:3.3.0-preview1 ruby --version
ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
This could be solved by always adding the executed program to $LOADED_FEATURES
.
As a workaround, executed programs can be prepended with:
require "pathname"
if __FILE__ == $0
$LOADED_FEATURES << Pathname.new(__FILE__).expand_path.to_s
end
Updated by johannes (Johannes Krude) over 1 year ago
- ruby -v set to ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
Making this change would not be backwards compatible:
# a.rb
if __FILE__ == $0
# $LOADED_FEATURES << File.expand_path(__FILE__) # would break things
require './b'
else
def a
1
end
end
# b.rb
require './a'
p a
The main script is treated specially compared to required files, in ways beyond this. I'm not sure that it is worth changing this and introducing backwards compatibility issues. Especially since this would still be a circular require, which Ruby issues a warning for in verbose warning mode.
Updated by Eregon (Benoit Daloze) over 1 year ago
A similar case that I have found surprising is if e.g. I use a file for a quick test called like a stdlib, say openssl.rb
, then require 'openssl'
in that file would not require the stdlib but load the main script a second time, if -I.
or so.
That's really unfortunate.
It seems pretty clear nobody wants to load the main script twice, so what's the compatibility issue with adding (the absolute path of the) main script to $LOADED_FEATURES like other (require'd) files?
Updated by nobu (Nobuyoshi Nakada) over 1 year ago
- Subject changed from Script loadde twice when requiring self to Script loaded twice when requiring self
Updated by matz (Yukihiro Matsumoto) over 1 year ago
Proposed change would break irb
at least. Please accept this weird behavior.
Matz.
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
- Status changed from Open to Rejected
Updated by mame (Yusuke Endoh) over 1 year ago
A few additional explanations.
First, the importance of the stated problem is not clear. Circular require should be fixed. The OP should clearly state the background for wanting this resolved (if any).
Also, a critical problem was noted that irb and many CLI tools would stop working with the proposed solution. For example, bin/irb does require "irb"
. With the proposed workaround, $LOADED_FEATRUES
will contain "/path/to/bin/irb"
when the irb command is executed. Then require "irb"
will not read /path/to/lib/irb.rb
, instead return false immediately. Thus, this proposal will make irb and many other CLI tools inoperable.
Updated by Eregon (Benoit Daloze) over 1 year ago
mame (Yusuke Endoh) wrote in #note-7:
With the proposed workaround,
$LOADED_FEATRUES
will contain"/path/to/bin/irb"
when the irb command is executed. Thenrequire "irb"
will not read/path/to/lib/irb.rb
, instead return false immediately. Thus, this proposal will make irb and many other CLI tools inoperable.
Unless I'm missing something, that would be no problem.
Because /path/to/bin
is not in $LOAD_PATH
so it won't be considered for require "irb"
, isn't it?