Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
How does require_relative work
The
require_relativemethod 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 originalrequire_relativeit will not work as expected. Here is the c-code forrequire_relativehttps://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::Locationclass: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:That behavior had the side effect of breaking gems that were using
Thread::Backtrace::Location#absolute_pathto implementrequire_relativein their monkey patch (such asbootsnapandderailed_benchmarks). The fix is easy enough, whileabsolute_pathreturns a nil thepathstill returns a value for eval code.This commit
Basically checks if
Thread::Backtrace::Location#absolute_pathis nil and if so, falls back toThread::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: