def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
klass, singleton = recv_orig.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
found = false
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
@sig_rets.each do |msig, ret_ty|
ncaller_env = caller_env
subst = aargs.consistent_with_method_signature?(msig)
next unless subst
if direct_method && recv_orig.is_a?(Type::Local)
ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
end
subst = Type.merge_substitution(subst, cur_subst)
subst[Type::Var.new(:self)] = recv
found = true
if aargs.blk_ty.is_a?(Type::Proc)
dummy_ctx = TypedContext.new(caller_ep, mid)
dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
s_recv = recv
s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
if msig.blk_ty.is_a?(Type::Proc)
scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
bsig = msig.blk_ty.block_body.msig
alloc_site = AllocationSite.new(caller_ep).add_id(self)
nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
ty
end
0.upto(bsig.opt_tys.size) do |n|
naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil)
scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
if subst2
subst2 = Type.merge_substitution(subst, subst2)
if direct_method && recv_orig.is_a?(Type::Local)
ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
end
ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
else
ret_ty2 = Type.any
end
scratch.add_return_value!(dummy_ctx, ret_ty2)
end
end
else
ret_ty = ret_ty.remove_type_vars
ctn[ret_ty, caller_ep, ncaller_env]
end
else
ret_ty = ret_ty.substitute(subst, Config.options[:type_depth_limit])
ret_ty = ret_ty.remove_type_vars
ctn[ret_ty, caller_ep, ncaller_env]
end
end
unless found
scratch.error(caller_ep, "failed to resolve overload: #{ recv.screen_name(scratch) }##{ mid }")
ctn[Type.any, caller_ep, caller_env]
end
end