Skip to content

Commit 3ea400f

Browse files
sekito1107mame
authored andcommitted
Add builtin type inference for Kernel#Array
Handle Kernel#Array in MAsgnBox#run0 by registering kernel_array_conv as a builtin handler. Previously, TypeProf had no special handling for Kernel#Array, causing the argument type to be returned unchanged rather than always returning an Array type. The handler correctly mirrors Ruby's Kernel#Array behavior: - Range[Elem] -> Array[Elem] (via to_a) - Array[Elem] -> Array[Elem] (pass through) - Literal array -> same type (pass through) - Other types (T) -> Array[T] (wrap)
1 parent 79fc821 commit 3ea400f

2 files changed

Lines changed: 58 additions & 0 deletions

File tree

lib/typeprof/core/builtin.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,44 @@ def kernel_send(changes, node, ty, a_args, ret)
247247
true
248248
end
249249

250+
def kernel_array(changes, node, ty, a_args, ret)
251+
return false unless a_args.positionals.size == 1
252+
253+
arg_vtx = a_args.positionals[0]
254+
elem_vtx = Vertex.new(node)
255+
handled = false
256+
needs_elem_wrap = false
257+
258+
arg_vtx.each_type do |arg_ty|
259+
handled = true
260+
case arg_ty
261+
when Type::Instance
262+
if arg_ty.mod == @genv.mod_range && arg_ty.args && !arg_ty.args.empty?
263+
changes.add_edge(@genv, arg_ty.args[0], elem_vtx)
264+
needs_elem_wrap = true
265+
elsif arg_ty.mod == @genv.mod_ary
266+
changes.add_edge(@genv, Source.new(arg_ty), ret)
267+
else
268+
changes.add_edge(@genv, Source.new(arg_ty), elem_vtx)
269+
needs_elem_wrap = true
270+
end
271+
when Type::Array
272+
changes.add_edge(@genv, Source.new(arg_ty), ret)
273+
else
274+
changes.add_edge(@genv, Source.new(arg_ty), elem_vtx)
275+
needs_elem_wrap = true
276+
end
277+
end
278+
279+
return false unless handled
280+
281+
if needs_elem_wrap
282+
ary_ty = @genv.gen_ary_type(elem_vtx)
283+
changes.add_edge(@genv, Source.new(ary_ty), ret)
284+
end
285+
true
286+
end
287+
250288
def deploy
251289
[
252290
[method(:class_new), [:Class], false, :new],
@@ -262,6 +300,7 @@ def deploy
262300
[method(:kernel_send), [:BasicObject], false, :__send__],
263301
[method(:kernel_send), [:Kernel], false, :public_send],
264302
[method(:kernel_send), [:Kernel], false, :send],
303+
[method(:kernel_array), [:Kernel], false, :Array],
265304
].each do |builtin, cpath, singleton, mid|
266305
me = @genv.resolve_method(cpath, singleton, mid)
267306
me.builtin = builtin

scenario/misc/kernel_array.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## update
2+
def from_range
3+
Array(1..5)
4+
end
5+
6+
def from_literal_array
7+
Array([1, 2, 3])
8+
end
9+
10+
def from_integer
11+
Array(42)
12+
end
13+
14+
## assert
15+
class Object
16+
def from_range: -> Array[Integer]
17+
def from_literal_array: -> [Integer, Integer, Integer]
18+
def from_integer: -> Array[Integer]
19+
end

0 commit comments

Comments
 (0)