Commit 5913e2f
committed
Support Ruby 3.1
## How does require_relative work
The `require_relative` method is different from other monkey patches because the code uses the caller location to change behavior. That means if you monkey patch that method and alias it back to the original `require_relative` it will not work as expected. Here is the c-code for `require_relative` https://github.com/ruby/ruby/blob/b35b7a1ef25347735a6bb7c28ab7e77afea1d856/load.c#L907-L924.
The way that bootsnap (and others) work around this limitation is by grabbing the second to last caller location and requiring relative to that file instead. This method uses the `Thread::Backtrace::Location` class:
```
caller_locations(1..1).first.class
=> Thread::Backtrace::Location
```
## What changed in 3.1
This change in ruby ruby/ruby#4519 changed the behavior of that class when being returned against code with an `eval`. It appears that previously the behavior was to return the path of the file where the eval was defined. The new behavior is to return a nil, and then that would be used to implement the behavior described:
```
if (!eval_default_path) {
eval_default_path = rb_fstring_lit("(eval)");
rb_gc_register_mark_object(eval_default_path);
}
fname = eval_default_path;
```
That behavior had the side effect of breaking gems that were using `Thread::Backtrace::Location#absolute_path` to implement `require_relative` in their monkey patch (such as `bootsnap` and `derailed_benchmarks`). The fix is easy enough, while `absolute_path` returns a nil the `path` still returns a value for eval code.
## This commit
Basically checks if `Thread::Backtrace::Location#absolute_path` is nil and if so, falls back to `Thread::Backtrace::Location#path`. The previous online was a little incomprehensible, so I refactored it a bit to highlight what's going on.
I found out about this fix from rails/bootsnap@0d64e7e after realizing that the test suite was failing on Ruby 3.1:
```
/home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:663:in `rescue in eval_gemspec': (Bundler::Dsl::DSLError)
[!] There was an error parsing `Gemfile`:
[!] There was an error while loading `dead_end.gemspec`: cannot load such file -- /home/circleci/lib/dead_end/version. Bundler cannot continue.
# from /home/circleci/project/dead_end.gemspec:3
# -------------------------------------------
#
> require_relative "lib/dead_end/version"
#
# -------------------------------------------
. Bundler cannot continue.
# from /home/circleci/project/Gemfile:6
# -------------------------------------------
# # Specify your gem's dependencies in dead_end.gemspec
> gemspec
#
# -------------------------------------------
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:658:in `eval_gemspec'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:585:in `block in load_gemspec_uncached'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/shared_helpers.rb:52:in `chdir'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/shared_helpers.rb:52:in `block in chdir'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/shared_helpers.rb:51:in `synchronize'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/shared_helpers.rb:51:in `chdir'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:584:in `load_gemspec_uncached'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:570:in `load_gemspec'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:66:in `block in gemspec'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:66:in `map'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:66:in `gemspec'
from /home/circleci/project/Gemfile:6:in `eval_gemfile'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:47:in `instance_eval'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:47:in `eval_gemfile'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/dsl.rb:12:in `evaluate'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/definition.rb:33:in `build'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:196:in `definition'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler.rb:144:in `setup'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/setup.rb:20:in `block in <top (required)>'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/ui/shell.rb:136:in `with_level'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/ui/shell.rb:88:in `silence'
from /home/circleci/.rvm/gems/ruby-3.1.0-preview1/gems/bundler-2.2.30/lib/bundler/setup.rb:20:in `<top (required)>'
from <internal:/home/circleci/.rvm/rubies/ruby-3.1.0-preview1/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from <internal:/home/circleci/.rvm/rubies/ruby-3.1.0-preview1/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
from /home/circleci/project/lib/dead_end/core_ext.rb:19:in `require'
```1 parent c4ce262 commit 5913e2f
File tree
4 files changed
+27
-5
lines changed- .circleci
- lib/dead_end
- spec/integration
4 files changed
+27
-5
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
48 | 59 | | |
49 | 60 | | |
50 | 61 | | |
| |||
61 | 72 | | |
62 | 73 | | |
63 | 74 | | |
| 75 | + | |
64 | 76 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
29 | 31 | | |
30 | 32 | | |
31 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
28 | 27 | | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
31 | 38 | | |
32 | | - | |
| 39 | + | |
33 | 40 | | |
34 | 41 | | |
35 | | - | |
| 42 | + | |
36 | 43 | | |
37 | 44 | | |
38 | 45 | | |
| |||
0 commit comments