Skip to content

Commit

Permalink
Showing 3 changed files with 28 additions and 2 deletions.
22 changes: 22 additions & 0 deletions spec/compiler/codegen/closure_spec.cr
Original file line number Diff line number Diff line change
@@ -639,4 +639,26 @@ describe "Code gen: closure" do
coco
)).to_i.should eq(1)
end

it "codegens closured self in block (#3388)" do
run(%(
class Foo
def initialize(@x : Int32)
end
def x
@x
end
def foo
yield
->{ self }
end
end
foo = Foo.new(42)
foo2 = foo.foo { }
foo2.call.x
)).to_i.should eq(42)
end
end
3 changes: 2 additions & 1 deletion src/compiler/crystal/codegen/call.cr
Original file line number Diff line number Diff line change
@@ -254,8 +254,9 @@ class Crystal::CodeGenVisitor
set_ensure_exception_handler(node)
set_ensure_exception_handler(target_def)

args_base_index = create_local_copy_of_block_self(self_type, call_args)
alloca_vars target_def.vars, target_def
create_local_copy_of_block_args(target_def, self_type, call_args)
create_local_copy_of_block_args(target_def, self_type, call_args, args_base_index)

Phi.open(self, node) do |phi|
context.return_phi = phi
5 changes: 4 additions & 1 deletion src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
@@ -368,13 +368,16 @@ class Crystal::CodeGenVisitor
end
end

def create_local_copy_of_block_args(target_def, self_type, call_args)
def create_local_copy_of_block_self(self_type, call_args)
args_base_index = 0
if self_type.passed_as_self?
context.vars["self"] = LLVMVar.new(call_args[0], self_type, true)
args_base_index = 1
end
args_base_index
end

def create_local_copy_of_block_args(target_def, self_type, call_args, args_base_index)
target_def.args.each_with_index do |arg, i|
create_local_copy_of_arg(target_def, target_def.vars, arg, call_args[args_base_index + i])
end

0 comments on commit 872f099

Please sign in to comment.