def do_check_send(msig, recv, mid, ep, scratch)
klass, singleton = recv.method_dispatch_info
cur_subst = {}
direct_method = true
scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
direct_method &&= direct
cur_subst = Type.merge_substitution(cur_subst, subst)
end
lead_num = @iseq.fargs_format[:lead_num] || 0
post_num = @iseq.fargs_format[:post_num] || 0
rest_start = @iseq.fargs_format[:rest_start]
opt = @iseq.fargs_format[:opt] || [0]
if rest_start
else
if msig.rest_ty
scratch.error(ep, "RBS says that a rest argument is accepted, but the method definition does not accept one")
return
end
if msig.lead_tys.size + msig.post_tys.size < lead_num + post_num
scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at least %d arguments" % [msig.lead_tys.size + msig.post_tys.size, lead_num + post_num])
return
end
if msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size > lead_num + opt.size - 1 + post_num
scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at most %d arguments" % [msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size, lead_num + opt.size - 1 + post_num])
return
end
end
lead_num = @iseq.fargs_format[:lead_num] || 0
post_start = @iseq.fargs_format[:post_start]
kw_start = @iseq.fargs_format[:kwbits]
keyword = @iseq.fargs_format[:keyword]
kw_start -= keyword.size if kw_start
kw_rest = @iseq.fargs_format[:kwrest]
block_start = @iseq.fargs_format[:block_start]
ctx = Context.new(@iseq, @cref, mid)
callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
locals = [Type.nil] * @iseq.locals.size
nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
alloc_site = AllocationSite.new(callee_ep)
idx = 0
msig.lead_tys.each_with_index do |ty, i|
alloc_site2 = alloc_site.add_id(idx += 1)
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(i, ty)
end
if msig.opt_tys
msig.opt_tys.each_with_index do |ty, i|
alloc_site2 = alloc_site.add_id(idx += 1)
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(lead_num + i, ty)
end
end
if msig.rest_ty
alloc_site2 = alloc_site.add_id(idx += 1)
ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(rest_start, rest_ty)
end
if msig.post_tys
msig.post_tys.each_with_index do |ty, i|
alloc_site2 = alloc_site.add_id(idx += 1)
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(post_start + i, ty)
end
end
if msig.kw_tys && keyword
msig.kw_tys.each do |_, key, ty|
i = keyword.index {|callee_key,| callee_key == key }
unless i
next
end
alloc_site2 = alloc_site.add_id(key)
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(kw_start + i, ty)
end
end
if msig.kw_rest_ty
ty = msig.kw_rest_ty
alloc_site2 = alloc_site.add_id(:**)
ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars
nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
nenv = nenv.local_update(kw_rest, ty)
end
nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
opt.each do |start_pc|
scratch.merge_env(callee_ep.jump(start_pc), nenv)
end
scratch.add_executed_iseq(@iseq)
ctx
end