From 6f64fbadaafa4e7d14ef6d2908bd7d4303d49fa5 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Fri, 3 Apr 2026 19:28:55 +0900 Subject: [PATCH] Support narrowing for if (y = x) assignment in condition LocalVariableWriteNode now provides narrowings for the assigned variable, so `if (y = x)` correctly narrows y to non-nil in the then branch. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/typeprof/core/ast/variable.rb | 7 ++++++ scenario/flow/if_assign.rb | 42 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 scenario/flow/if_assign.rb diff --git a/lib/typeprof/core/ast/variable.rb b/lib/typeprof/core/ast/variable.rb index 8f11cef55..fc34adc0c 100644 --- a/lib/typeprof/core/ast/variable.rb +++ b/lib/typeprof/core/ast/variable.rb @@ -68,6 +68,13 @@ def retrieve_at(pos, &blk) super(pos, &blk) end + def narrowings + @narrowings ||= [ + Narrowing.new({ @var => Narrowing::NilConstraint.new(false) }), + Narrowing.new({ @var => Narrowing::NilConstraint.new(true) }), + ] + end + def modified_vars(tbl, vars) vars << self.var if tbl.include?(self.var) end diff --git a/scenario/flow/if_assign.rb b/scenario/flow/if_assign.rb new file mode 100644 index 000000000..a4c823762 --- /dev/null +++ b/scenario/flow/if_assign.rb @@ -0,0 +1,42 @@ +## update +def foo(x) + if (y = x) + y.to_sym + end +end +foo(nil) +foo("hello") + +## assert +class Object + def foo: (String?) -> Symbol? +end + +## update +def foo(x, z) + if x && (y = z) + y.to_sym + end +end +foo(true, "hello") +foo(true, nil) +foo(false, nil) + +## assert +class Object + def foo: (bool, String?) -> Symbol? +end + +## update +def foo(z) + if (y = z) && y.length > 0 + y.to_sym + end +end +foo("hello") +foo(nil) + +## assert +class Object + def foo: (String?) -> Symbol? +end