diff --git a/spec/compiler/codegen/fun_spec.cr b/spec/compiler/codegen/fun_spec.cr index 7879c04cd18b22b8c8d7bb2b68af631f09756899..4fe078742a1cb8ec4e3414b7cf1c85b9c036f52c 100644 --- a/spec/compiler/codegen/fun_spec.cr +++ b/spec/compiler/codegen/fun_spec.cr @@ -485,4 +485,22 @@ describe "Code gen: fun" do foo.call(a).to_i )).to_i.should eq(1) end + + it "codegens issue with missing byval in fun literal inside struct" do + run(%( + require "prelude" + + struct Params + def foo + params = [] of {String} + params << {"foo"} + params << {"bar"} + params.sort! { |x, y| x[0] <=> y[0] } + params[0][0] + end + end + + Params.new.foo + )).to_string.should eq("bar") + end end diff --git a/src/compiler/crystal/codegen/fun.cr b/src/compiler/crystal/codegen/fun.cr index 02f66af7160fc4741c1e79ce13d2690da8511a1a..ceff74a52d349954bd170b8d179572c0b42fad97 100644 --- a/src/compiler/crystal/codegen/fun.cr +++ b/src/compiler/crystal/codegen/fun.cr @@ -180,8 +180,10 @@ class Crystal::CodeGenVisitor < Crystal::Visitor # Set 'byval' attribute # but don't set it if it's the "self" argument and it's a struct (while not in a closure). - if arg.type.passed_by_value? && (is_closure || !(i == 0 && self_type.struct?)) - param.add_attribute LibLLVM::Attribute::ByVal + if arg.type.passed_by_value? + if (is_fun_literal && !is_closure) || (is_closure || !(i == 0 && self_type.struct?)) + param.add_attribute LibLLVM::Attribute::ByVal + end end end