From 9d5d61ffa3ed67e1b2e3881d29087ed4efb35238 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Tue, 24 Feb 2026 17:17:54 +0000 Subject: [PATCH 1/2] Remove unused LocalEnv#code_units_cache delegation method --- lib/typeprof/core/env.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/typeprof/core/env.rb b/lib/typeprof/core/env.rb index 6da8d0b2..91117468 100644 --- a/lib/typeprof/core/env.rb +++ b/lib/typeprof/core/env.rb @@ -333,8 +333,6 @@ def initialize(file_context, cref, locals, return_boxes) attr_reader :file_context, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope def path = @file_context&.path - def code_units_cache = @file_context&.code_units_cache - def code_range_from_node(node) TypeProf::CodeRange.from_node(node, @file_context&.code_units_cache) end From 353dc0e7b092c3b990a504dea9ce46bdb7203a7b Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Tue, 24 Feb 2026 17:20:03 +0000 Subject: [PATCH 2/2] Improve ForNode to process loop variable and track modified vars --- lib/typeprof/core/ast/misc.rb | 28 ++++++++++++++++++++++++---- scenario/misc/for-variable-leak.rb | 13 +++++++++++++ scenario/misc/for.rb | 1 - 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 scenario/misc/for-variable-leak.rb diff --git a/lib/typeprof/core/ast/misc.rb b/lib/typeprof/core/ast/misc.rb index cf69b92b..9c94bc5e 100644 --- a/lib/typeprof/core/ast/misc.rb +++ b/lib/typeprof/core/ast/misc.rb @@ -265,19 +265,39 @@ def install0(genv) class ForNode < Node def initialize(raw_node, lenv) super(raw_node, lenv) - # XXX: tentative implementation - # raw_node.index + @index = AST.create_target_node(raw_node.index, lenv) @expr = AST.create_node(raw_node.collection, lenv) @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.new(code_range.last, code_range.last), lenv) end - attr_reader :expr, :body + attr_reader :index, :expr, :body - def subnodes = { expr:, body: } + def subnodes = { index:, expr:, body: } def install0(genv) @expr.install(genv) + + vars = [] + @index.modified_vars(@lenv.locals.keys, vars) + @body.modified_vars(@lenv.locals.keys, vars) + vars.uniq! + + old_vtxs = {} + vars.each do |var| + vtx = @lenv.get_var(var) + nvtx = vtx.new_vertex(genv, self) + old_vtxs[var] = nvtx + @lenv.set_var(var, nvtx) + end + + @index.install(genv) @body.install(genv) + + vars.each do |var| + @changes.add_edge(genv, @lenv.get_var(var), old_vtxs[var]) + @lenv.set_var(var, old_vtxs[var]) + end + Source.new(genv.nil_type) end end diff --git a/scenario/misc/for-variable-leak.rb b/scenario/misc/for-variable-leak.rb new file mode 100644 index 00000000..2a04d1f7 --- /dev/null +++ b/scenario/misc/for-variable-leak.rb @@ -0,0 +1,13 @@ +## update +def foo + x = "hello" + for i in [1, 2, 3] + x = 42 + end + x +end + +## assert +class Object + def foo: -> (Integer | String) +end diff --git a/scenario/misc/for.rb b/scenario/misc/for.rb index e4fc8e01..718dd2df 100644 --- a/scenario/misc/for.rb +++ b/scenario/misc/for.rb @@ -1,7 +1,6 @@ ## update def foo for i in 1..100 - # currently, TypeProf does not initialize i return 1 end end