Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rbs/test: breaks instance_eval(&block) #479

Closed
palkan opened this issue Nov 19, 2020 · 1 comment · Fixed by #488
Closed

rbs/test: breaks instance_eval(&block) #479

palkan opened this issue Nov 19, 2020 · 1 comment · Fixed by #488
Assignees
Milestone

Comments

@palkan
Copy link
Contributor

palkan commented Nov 19, 2020

Example:

# a.rb
class A
  def eval_block(&block)
    instance_eval(&block)
  end
end

a = A.new

a.eval_block do
  raise "Failed" unless a == self
end

puts "OK"

# sig/a.rbs
class A
  def eval_block: { (self) -> void } -> void
end
$ ruby a.rb
OK

$ RBS_TEST_TARGET='A' ruby -r rbs/test/setup a.rb
I, [2020-11-19T14:45:33.792182 #57850]  INFO -- : Setting up hooks for ::A
I, [2020-11-19T14:45:33.792263 #57850]  INFO -- rbs: Installing runtime type checker in A...
I, [2020-11-19T14:45:33.795050 #57850]  INFO -- rbs: Setting up method hook in #eval_block...
Traceback (most recent call last):
        5: from a.rb:9:in `<main>'
        4: from /usr/local/lib/ruby/gems/2.6.0/gems/rbs-0.17.0/lib/rbs/test/hook.rb:81:in `eval_block__with__RBS_TEST_b1c5ff'
        3: from a.rb:3:in `eval_block'
        2: from a.rb:3:in `instance_eval'
        1: from /usr/local/lib/ruby/gems/2.6.0/gems/rbs-0.17.0/lib/rbs/test/hook.rb:85:in `block in eval_block__with__RBS_TEST_b1c5ff'
a.rb:10:in `block in <main>': Failed (RuntimeError)

Hijacking the passed block in hook.rb loses the possible execution context change information. Have no idea so far on how to fix this (except from adding a hack to track #instance_eval / #instance_exec usage):

rbs/lib/rbs/test/hook.rb

Lines 80 to 112 in 7914225

if block_given?
result = __send__(:"#{without_name}", *args) do |*block_args|
return_from_block = false
begin
block_result = yield(*block_args)
return_from_block = true
ensure
exn = $!
case
when return_from_block
# Returned from yield
block_calls << ::RBS::Test::ArgumentsReturn.return(
arguments: block_args,
value: block_result
)
when exn
# Exception
block_calls << ::RBS::Test::ArgumentsReturn.exception(
arguments: block_args,
exception: exn
)
else
# break?
block_calls << ::RBS::Test::ArgumentsReturn.break(
arguments: block_args
)
end
end
block_result
end

@soutaro
Copy link
Member

soutaro commented Nov 23, 2020

I was thinking of I implemented a workaround for this... Let me confirm.

@soutaro soutaro self-assigned this Nov 23, 2020
@soutaro soutaro added this to the Ruby 3.0 milestone Nov 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants