Skip to content

Commit 94d8a02

Browse files
committed
Fix rb prototype type for return with multiple values
For the first case it resovled to untyped For the second case, it was `Array | untyped` In both cases we know it will return an array
1 parent a80e4a9 commit 94d8a02

3 files changed

Lines changed: 46 additions & 12 deletions

File tree

lib/rbs/prototype/rb.rb

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,8 @@ def body_type(node)
669669
body_type(node.statements)
670670
when Prism::StatementsNode
671671
block_type(node)
672+
when Prism::ReturnNode
673+
return_node_to_type(node)
672674
else
673675
literal_to_type(node)
674676
end
@@ -678,21 +680,16 @@ def block_type(node)
678680
return_stmts = any_node?(node) do |n|
679681
n.is_a?(Prism::ReturnNode)
680682
end&.map do |return_node|
681-
return_args = return_node.arguments&.arguments || []
682-
return_types = return_args.map { |arg| literal_to_type(arg) }
683-
684-
if return_types.size >= 2
685-
t = types_to_union_type(return_types)
686-
BuiltinNames::Array.instance_type(t)
687-
else
688-
return_types.first || Types::Bases::Nil.new(location: nil)
689-
end
683+
return_node_to_type(return_node)
690684
end || []
691685

692686
last_node = node.compact_child_nodes.last
693-
last_evaluated = last_node ? literal_to_type(last_node) : Types::Bases::Nil.new(location: nil)
694-
# FIXME: Skipt if last_evaluated ReturnNode
695-
types_to_union_type([*return_stmts, last_evaluated])
687+
case last_node
688+
when nil, Prism::ReturnNode
689+
types_to_union_type(return_stmts)
690+
else
691+
types_to_union_type([*return_stmts, literal_to_type(last_node)])
692+
end
696693
end
697694

698695
def literal_to_symbol(node)
@@ -784,6 +781,18 @@ def literal_to_type(node)
784781
end
785782
end
786783

784+
def return_node_to_type(node)
785+
return_args = node.arguments&.arguments || []
786+
return_types = return_args.map { |arg| literal_to_type(arg) }
787+
788+
if return_types.size >= 2
789+
t = types_to_union_type(return_types)
790+
BuiltinNames::Array.instance_type(t)
791+
else
792+
return_types.first || Types::Bases::Nil.new(location: nil)
793+
end
794+
end
795+
787796
def types_to_union_type(types)
788797
return untyped if types.empty?
789798

sig/prototype/rb.rbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ module RBS
6262

6363
def block_type: (Prism::Node node) -> Types::t
6464

65+
def return_node_to_type: (Prism::ReturnNode) -> Types::t
66+
6567
def literal_to_type: (Prism::Node node) -> Types::t
6668

6769
def types_to_union_type: (Array[Types::t] types) -> Types::t

test/rbs/rb_prototype_test.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,29 @@ def with_unless: () -> (:sym | nil)
324324
EOR
325325
end
326326

327+
def test_defs_return_type_multiple
328+
rb = <<~RUBY
329+
class Hello
330+
def one_statement
331+
return 1, ""
332+
end
333+
334+
def multiple_statements
335+
foo
336+
return 1, ""
337+
end
338+
end
339+
RUBY
340+
341+
assert_write RB.parse(rb), <<~RBS
342+
class Hello
343+
def one_statement: () -> ::Array[1 | \"\"]
344+
345+
def multiple_statements: () -> ::Array[1 | \"\"]
346+
end
347+
RBS
348+
end
349+
327350
def test_sclass
328351
rb = <<-EOR
329352
class Hello

0 commit comments

Comments
 (0)