Skip to content

Commit 94d417d

Browse files
mameclaude
andcommitted
Fix optional type typecheck to accept nil
SigTyOptionalNode#typecheck was delegating directly to the inner type's typecheck, which would reject nil values for T? types like Binding?. Now it skips nil types when checking, since nil is always valid for optional types. This fixes false "wrong type of arguments" for calls like eval("code", nil, "filename") where the second argument is Binding?. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 885d081 commit 94d417d

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

lib/typeprof/core/ast/sig_type.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,16 @@ def contravariant_vertex0(genv, changes, vtx, subst)
884884
end
885885

886886
def typecheck(genv, changes, vtx, subst)
887+
# For optional type T?, check if all non-nil types match T.
888+
# nil is always acceptable.
889+
changes.add_edge(genv, vtx, changes.target)
890+
has_non_nil = false
891+
vtx.each_type do |ty|
892+
next if ty.is_a?(Type::Bot)
893+
next if ty == genv.nil_type
894+
has_non_nil = true
895+
end
896+
return true unless has_non_nil
887897
@type.typecheck(genv, changes, vtx, subst)
888898
end
889899

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
## update: test.rbs
2+
class Object
3+
def bar: (Binding?) -> void
4+
end
5+
6+
## update: test.rb
7+
eval("hello", nil, "test")
8+
9+
def bar_nil
10+
bar(nil)
11+
end
12+
13+
def bar_binding
14+
bar(binding)
15+
end
16+
17+
## assert
18+
class Object
19+
def bar_nil: -> Object
20+
def bar_binding: -> Object
21+
end

0 commit comments

Comments
 (0)