From 2129b7588cab5aec3d731395d19220f2f4a43c80 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Mon, 9 Feb 2026 18:25:39 +0900 Subject: [PATCH] Fix crash in break in loop This change avoids multi-edges by creating an intermediate vertex between an `break` argument and its iterator's result. Fixes #356 Co-Authored-By: pvcresin --- Gemfile.lock | 2 +- lib/typeprof/core/ast/control.rb | 2 +- scenario/control/break2.rb | 67 ++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 scenario/control/break2.rb diff --git a/Gemfile.lock b/Gemfile.lock index 67ccf5c3..f0a8db6a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - typeprof (0.31.0) + typeprof (0.31.1) prism (>= 1.4.0) rbs (>= 3.6.0) diff --git a/lib/typeprof/core/ast/control.rb b/lib/typeprof/core/ast/control.rb index ec521c8c..57027c6c 100644 --- a/lib/typeprof/core/ast/control.rb +++ b/lib/typeprof/core/ast/control.rb @@ -203,7 +203,7 @@ def subnodes = { arg: } def install0(genv) arg = @arg.install(genv) - @changes.add_edge(genv, arg, @lenv.get_break_vtx) + @changes.add_edge(genv, arg.new_vertex(genv, self), @lenv.get_break_vtx) Source.new() end end diff --git a/scenario/control/break2.rb b/scenario/control/break2.rb new file mode 100644 index 00000000..6daa4592 --- /dev/null +++ b/scenario/control/break2.rb @@ -0,0 +1,67 @@ +## update +def foo + count = 0 + loop do + count += 1 + break count if count == 3 + end +end + +## assert +class Object + def foo: -> Integer +end + +## update +def foo + count = 0 + loop do + count += 1 + begin + break count if count == 3 + rescue + break count + end + end +end + +## assert +class Object + def foo: -> Integer +end + +## update +def foo + count = 0 + loop do + count += 1 + begin + break count if count == 3 + rescue + break 'str' + end + end +end + +## assert +class Object + def foo: -> (Integer | String) +end + +## update +def foo + count = 0 + loop do + count += 1 + begin + # break count if count == 3 + rescue + break 'str' + end + end +end + +## assert +class Object + def foo: -> String +end