Skip to content

Commit 4d497e7

Browse files
mameclaude
andcommitted
Handle Array slice assignment (ary[start, len] = val) in builtin
Previously, Array#[]= with 3 arguments (slice assignment) fell through to RBS overload resolution, where both (int, int, Elem) and (int, int, Array[Elem]) overloads matched. The Elem overload caused the assigned array to be treated as an element, creating deeply nested union types like Array[Array[Array[Integer]]]. Now the builtin handles 3-argument []= by using SplatBox to extract element types from the assigned value and merge them into the array's element type, preventing type nesting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d31fa4b commit 4d497e7

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

lib/typeprof/core/builtin.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ def array_aset(changes, node, ty, a_args, ret)
6969
else
7070
false
7171
end
72+
elsif a_args.positionals.size == 3
73+
# ary[start, len] = val
74+
# Use SplatBox to extract element types from the assigned value
75+
elem_vtx = case ty
76+
when Type::Array
77+
ty.get_elem(@genv)
78+
when Type::Instance
79+
ty.mod == @genv.mod_ary ? ty.args[0] : nil
80+
end
81+
return false unless elem_vtx
82+
val = a_args.positionals[2]
83+
splat_ret = changes.add_splat_box(@genv, val).ret
84+
changes.add_edge(@genv, splat_ret, elem_vtx)
85+
true
7286
else
7387
false
7488
end

scenario/array/slice_aset.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## update
2+
def test
3+
a = [0] * 10
4+
a[0, 3] = [1, 2, 3]
5+
a[5, 3] = a[0, 3]
6+
a[0]
7+
end
8+
9+
test
10+
11+
## assert
12+
class Object
13+
def test: -> Integer
14+
end

0 commit comments

Comments
 (0)