diff --git a/lib/typeprof/core/env/method.rb b/lib/typeprof/core/env/method.rb index 6fdef35dc..fc7f2f8ea 100644 --- a/lib/typeprof/core/env/method.rb +++ b/lib/typeprof/core/env/method.rb @@ -397,30 +397,20 @@ def initialize(req_positionals, opt_positionals, rest_positionals, post_position @param_names = param_names end - # The arguments that `...` forwards: only the ones the caller passed. + # The arguments that `...` forwards: only the ones the caller passed to it. + # The parameters before `...` (`def foo(a, b = 1, ...)`) are not forwarded, + # and none can follow it. def to_actual_arguments(genv, changes, node) positionals = [] splat_flags = [] positionals_omittable = [] - @opt_positionals.each do |elem_vtx| - positionals << Source.new(genv.gen_ary_type(elem_vtx)) - splat_flags << true - positionals_omittable << true - end - if @rest_positionals positionals << Source.new(genv.gen_ary_type(@rest_positionals)) splat_flags << true positionals_omittable << true end - @post_positionals.each do |arg| - positionals << arg - splat_flags << false - positionals_omittable << false - end - # `...` cannot follow keyword parameters, so only the rest keywords remain ForwardingActualArguments.new(positionals, splat_flags, @rest_keywords, @block, positionals_omittable, !!@rest_keywords, true, @activation, true) end diff --git a/scenario/args/forwarding_arguments.rb b/scenario/args/forwarding_arguments.rb index 7eb580e0d..c766b52b3 100644 --- a/scenario/args/forwarding_arguments.rb +++ b/scenario/args/forwarding_arguments.rb @@ -132,3 +132,21 @@ class Object def foo: (*Integer, **Integer) -> Integer def bar: (*Integer, **Integer) -> [Array[Integer], { x: Integer, y: Integer }] end + +## update +# `...` forwards only what it takes, not the optional parameters before it +def foo(a = 1, ...) + bar(...) +end + +def bar(*r) + r +end + +foo(:sym, "str") + +## assert +class Object + def foo: (?:sym | Integer, *String, **untyped) -> Array[String] + def bar: (*String) -> Array[String] +end