Class: TypeProf::TypedMethodDef
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
MethodDef
|
|
Instance Chain:
|
|
Inherits: |
TypeProf::MethodDef
|
Defined in: | lib/typeprof/method.rb |
Class Method Summary
-
.new(sig_rets, rbs_source, pub_meth) ⇒ TypedMethodDef
constructor
sig_rets: Array<[MethodSignature, (return)Type]>.
Instance Attribute Summary
Instance Method Summary
Constructor Details
.new(sig_rets, rbs_source, pub_meth) ⇒ TypedMethodDef
sig_rets: Array<[MethodSignature, (return)Type]>
# File 'lib/typeprof/method.rb', line 231
def initialize(sig_rets, rbs_source, pub_meth) # sig_rets: Array<[MethodSignature, (return)Type]> @sig_rets = sig_rets @rbs_source = rbs_source @pub_meth = pub_meth @iseq = nil end
Instance Attribute Details
#iseq (readonly)
[ GitHub ]# File 'lib/typeprof/method.rb', line 238
attr_reader :rbs_source, :iseq
#rbs_source (readonly)
[ GitHub ]# File 'lib/typeprof/method.rb', line 238
attr_reader :rbs_source, :iseq
Instance Method Details
#do_match_iseq_mdef(iseq_mdef, recv, mid, env, ep, scratch)
[ GitHub ]# File 'lib/typeprof/method.rb', line 325
def do_match_iseq_mdef(iseq_mdef, recv, mid, env, ep, scratch) recv = scratch.globalize_type(recv, env, ep) @sig_rets.each do |msig, _ret_ty| iseq_mdef.do_check_send(msig, recv, mid, ep, scratch) end @iseq ||= iseq_mdef.iseq end
#do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
[ GitHub ]# File 'lib/typeprof/method.rb', line 240
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 #pp [mid, aargs, msig] # XXX: support self type in msig 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) # need to check self tyvar? subst[Type::Var.new(:self)] = recv found = true if aargs.blk_ty.is_a?(Type::Proc) #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX 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.current. [: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) # XXX: support block to block? 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.current. [:type_depth_limit]).remove_type_vars else ret_ty2 = Type.any end # XXX: check the return type from the block # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ??? scratch.add_return_value!(dummy_ctx, ret_ty2) end # scratch.add_return_value!(dummy_ctx, ret_ty) ? # This makes `def foo; 1.times { return "str" }; end` return Integer|String end else # XXX: a block is passed to a method that does not accept block. # Should we call the passed block with any arguments? ret_ty = ret_ty.remove_type_vars ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot end else ret_ty = ret_ty.substitute(subst, Config.current. [:type_depth_limit]) ret_ty = ret_ty.remove_type_vars ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot 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