Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: dec5d9a72dbc
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 31693b5aa877
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Feb 8, 2017

  1. Fixed #3991: Wrong debug info for block argument passed with &

    Ary Borenszweig committed Feb 8, 2017
    Copy the full SHA
    4ca7aa0 View commit details
  2. Fixed #4002: local variable re-assignment in rescue block doesn't mer…

    …ge types only after that point
    Ary Borenszweig committed Feb 8, 2017
    Copy the full SHA
    31693b5 View commit details
12 changes: 12 additions & 0 deletions spec/compiler/semantic/exception_spec.cr
Original file line number Diff line number Diff line change
@@ -442,4 +442,16 @@ describe "Semantic: exception" do
a
)) { int32 }
end

it "doesn't infect type to variable before handler (#4002)" do
assert_type(%(
a = 1
b = a
begin
a = 'a'
rescue
end
b
)) { int32 }
end
end
6 changes: 3 additions & 3 deletions src/compiler/crystal/codegen/call.cr
Original file line number Diff line number Diff line change
@@ -290,12 +290,12 @@ class Crystal::CodeGenVisitor
end

def codegen_call_with_block_as_fun_literal(node, fun_literal, self_type, call_args)
target_def = node.target_def
func = target_def_fun(target_def, self_type)

fun_literal.accept self
call_args.push @last

target_def = node.target_def
func = target_def_fun(target_def, self_type)

codegen_call_or_invoke(node, target_def, self_type, func, call_args, target_def.raises?, target_def.type)
end

4 changes: 2 additions & 2 deletions src/compiler/crystal/semantic/call.cr
Original file line number Diff line number Diff line change
@@ -534,11 +534,11 @@ class Crystal::Call
vars = [] of Var
args = [] of ASTNode
block_arg_type.arg_types.map_with_index do |type, i|
arg = Var.new("__arg#{i}")
arg = Var.new("__arg#{i}").at(block_arg)
vars << arg
args << arg
end
block = Block.new(vars, Call.new(block_arg.clone, "call", args).at(block_arg))
block = Block.new(vars, Call.new(block_arg.clone, "call", args).at(block_arg)).at(block_arg)
block.vars = self.before_vars
self.block = block
else
7 changes: 7 additions & 0 deletions src/compiler/crystal/semantic/main_visitor.cr
Original file line number Diff line number Diff line change
@@ -2485,7 +2485,14 @@ module Crystal
# Any variable assigned in the body (begin) will have, inside rescue
# blocks, all types that were assigned to them, because we can't know at which
# point an exception is raised.
# We create different vars, though, to avoid changing the type of vars
# before the handler.
exception_handler_vars = @exception_handler_vars = @vars.dup
exception_handler_vars.each do |name, var|
new_var = new_meta_var(name)
new_var.bind_to(var)
exception_handler_vars[name] = new_var
end

node.body.accept self