Project

General

Profile

Actions

Bug #19726

closed

Script loaded twice when requiring self

Added by johannes (Johannes Krude) over 1 year ago. Updated over 1 year ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 3.3.0preview1 (2023-05-12 master a1b01e7701) [x86_64-linux]
[ruby-core:113888]

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
Actions #1

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?

Actions #4

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.

Actions #6

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. 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.

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?

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0Like0Like0Like0