-
-
Notifications
You must be signed in to change notification settings - Fork 358
restore_original_visibility crashing when prepended modules and refinements both exist #1395
Comments
I submitted an issue to the Ruby tracker: https://bugs.ruby-lang.org/issues/17519 |
Thanks, @fledman ! |
Might be related #1101 |
unfortunately no one has responded to my Ruby bug report |
@JonRowe do you think it makes sense to summon someone from the Ruby core team to take a quick look? |
if you can get someone to take a look, that would be helpful |
@jeremyevans @eregon may I kindly ask you to take a look, please? |
@pirj That bug is on my radar, I hope to have time to look into it before the end of the month. |
If it helps, the Ruby 2.7.3 release contains this fix, and the tests that were failing for me before with the error described in this issue are passing on 2.7.3! |
the Ruby 2.7.3 release did fix this particular bug, so we can probably close the issue FYI it introduced another similar bug, see ruby/ruby#4200 (comment) |
Awesome! |
Subject of the issue
the
restore_original_visibility
step of resetting a method double crashes when both of the following conditions are true:Your environment
Steps to reproduce
Expected behavior
The tests pass without any errors
Actual behavior
Related Issues
rspec/rspec-rails#2394 seems to just be this issue under the hood
#1218 is a broader change, but may actually resolve this?
Resolution Thoughts
The problem seems to be a mismatch between stashing and cleanup.
Before stashing, we check definition and ownership:
rspec-mocks/lib/rspec/mocks/instance_method_stasher.rb
Lines 100 to 110 in 7c492bd
While before restoring visibility, we just check definition:
rspec-mocks/lib/rspec/mocks/method_double.rb
Lines 104 to 109 in 7c492bd
That is why I expect this subset of the diff from #1218 to resolve things:
The reason that the current code mostly works is that the ruby
set_visibility
*** function is inconsistent. If you call it on a singleton class where the method in question is defined in an ancestor, it works most of the time. However, it fails when a refinement and a prepended module are both present. I am not sure which of the following is true:set_visibility
should be called on the module where the method is defined; rspec-mocks should not expect Ruby to walk the ancestor treeset_visibility
works as rspec-mocks currently uses it, and this is a bug in Rubyif (1) is the case, then we could also fix things by passing
false
to the three_method_defined?
calls, to prevent searching the ancestor tree in our method existence check:rspec-mocks/lib/rspec/mocks/method_reference.rb
Lines 67 to 68 in 7c492bd
EDIT: (1) is also a Ruby bug: if
set_visibility
has constraints, then they should be enforced consistently***
set_visibility
is the C function public/private/protected delegate toThe text was updated successfully, but these errors were encountered: