typeprof 0.4.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -2
- data/Gemfile.lock +3 -3
- data/README.md +6 -0
- data/lib/typeprof/analyzer.rb +97 -84
- data/lib/typeprof/arguments.rb +27 -19
- data/lib/typeprof/block.rb +5 -2
- data/lib/typeprof/builtin.rb +14 -4
- data/lib/typeprof/config.rb +10 -6
- data/lib/typeprof/container-type.rb +117 -101
- data/lib/typeprof/export.rb +1 -1
- data/lib/typeprof/import.rb +44 -22
- data/lib/typeprof/method.rb +70 -12
- data/lib/typeprof/type.rb +108 -89
- data/lib/typeprof/version.rb +1 -1
- data/smoke/arguments2.rb +1 -1
- data/smoke/array11.rb +1 -1
- data/smoke/array6.rb +2 -2
- data/smoke/array8.rb +1 -1
- data/smoke/block-args2.rb +3 -3
- data/smoke/block-args3.rb +4 -4
- data/smoke/block-blockarg.rb +1 -1
- data/smoke/block-kwarg.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/block5.rb +1 -1
- data/smoke/constant2.rb +1 -2
- data/smoke/demo5.rb +1 -1
- data/smoke/demo9.rb +1 -1
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/hash-merge-bang.rb +11 -0
- data/smoke/hash1.rb +3 -2
- data/smoke/hash3.rb +1 -1
- data/smoke/inheritance2.rb +2 -2
- data/smoke/ivar2.rb +2 -2
- data/smoke/kernel-class.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/kwsplat1.rb +2 -2
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/parameterizedd-self.rb +2 -2
- data/smoke/pattern-match1.rb +23 -0
- data/smoke/pattern-match2.rb +15 -0
- data/smoke/rbs-tyvar3.rb +11 -19
- data/smoke/rbs-tyvar3.rbs +4 -3
- data/smoke/rbs-tyvar4.rb +36 -0
- data/smoke/rbs-tyvar5.rb +12 -0
- data/smoke/rbs-tyvar5.rbs +8 -0
- data/smoke/struct.rb +2 -2
- data/smoke/uninitialize-var.rb +12 -0
- data/smoke/union-recv.rb +2 -2
- data/typeprof.gemspec +1 -1
- metadata +11 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2d60066fe3965ec65f9885e311f856277d0e41330478489c026fdf6b387ba2ba
         | 
| 4 | 
            +
              data.tar.gz: 963b66fe97d98207d72645011bcd012368937ded76278d92a4b677b961c92cdc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a40e89e05c1680480eb66798863ab99a4b38b3faaacdc471a6cdd45dfc1f897efcc8f613800ef28e5bc722c3504dec510ca943435873b6cb765a27f1bb073425
         | 
| 7 | 
            +
              data.tar.gz: 94dddf2c3e465ee19093ce571d50440293118b07ab7c90203aa5ccb40c4f9eb9afe1059eff045c965006affa8f0d66d141be2064feddf9a2b1f8384f8cadae64
         | 
    
        data/.github/workflows/main.yml
    CHANGED
    
    | @@ -17,9 +17,8 @@ jobs: | |
| 17 17 | 
             
                  uses: ruby/setup-ruby@v1
         | 
| 18 18 | 
             
                  with:
         | 
| 19 19 | 
             
                    ruby-version: ${{ matrix.ruby-version }}
         | 
| 20 | 
            -
                - name:  | 
| 20 | 
            +
                - name: Bundle install
         | 
| 21 21 | 
             
                  run: |
         | 
| 22 | 
            -
                    cd rbs && bundle install && bundle exec rake parser && cd ..
         | 
| 23 22 | 
             
                    bundle install
         | 
| 24 23 | 
             
                - name: Run the test suite
         | 
| 25 24 | 
             
                  run: |
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                typeprof (0.4 | 
| 5 | 
            -
                  rbs (>= 0. | 
| 4 | 
            +
                typeprof (0.5.4)
         | 
| 5 | 
            +
                  rbs (>= 0.17.0)
         | 
| 6 6 |  | 
| 7 7 | 
             
            GEM
         | 
| 8 8 | 
             
              remote: https://rubygems.org/
         | 
| @@ -11,7 +11,7 @@ GEM | |
| 11 11 | 
             
                docile (1.3.2)
         | 
| 12 12 | 
             
                power_assert (1.2.0)
         | 
| 13 13 | 
             
                rake (13.0.1)
         | 
| 14 | 
            -
                rbs (0. | 
| 14 | 
            +
                rbs (0.17.0)
         | 
| 15 15 | 
             
                simplecov (0.19.1)
         | 
| 16 16 | 
             
                  docile (~> 1.1)
         | 
| 17 17 | 
             
                  simplecov-html (~> 0.11)
         | 
    
        data/README.md
    CHANGED
    
    
    
        data/lib/typeprof/analyzer.rb
    CHANGED
    
    | @@ -87,6 +87,11 @@ module TypeProf | |
| 87 87 | 
             
                  @recv_ty = recv_ty
         | 
| 88 88 | 
             
                  @blk_ty = blk_ty
         | 
| 89 89 | 
             
                  @mod_func = mod_func
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  return if recv_ty == :top #OK
         | 
| 92 | 
            +
                  recv_ty.each_child_global do |ty|
         | 
| 93 | 
            +
                    raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && ty != Type.any
         | 
| 94 | 
            +
                  end
         | 
| 90 95 | 
             
                end
         | 
| 91 96 |  | 
| 92 97 | 
             
                attr_reader :recv_ty, :blk_ty, :mod_func
         | 
| @@ -129,11 +134,7 @@ module TypeProf | |
| 129 134 | 
             
                        elems2 = type_params[id]
         | 
| 130 135 | 
             
                        if elems2
         | 
| 131 136 | 
             
                          if elems != elems2
         | 
| 132 | 
            -
                             | 
| 133 | 
            -
                              type_params[id] = elems.zip(elems2).map {|elem1, elem2| elem1.union(elem2) }
         | 
| 134 | 
            -
                            else
         | 
| 135 | 
            -
                              type_params[id] = elems.union(elems2)
         | 
| 136 | 
            -
                            end
         | 
| 137 | 
            +
                            type_params[id] = elems.union(elems2)
         | 
| 137 138 | 
             
                          end
         | 
| 138 139 | 
             
                        else
         | 
| 139 140 | 
             
                          type_params[id] = elems
         | 
| @@ -151,6 +152,8 @@ module TypeProf | |
| 151 152 | 
             
                  tys.each do |ty|
         | 
| 152 153 | 
             
                    raise "nil cannot be pushed to the stack" if ty.nil?
         | 
| 153 154 | 
             
                    ty.each_child do |ty|
         | 
| 155 | 
            +
                      raise if ty.is_a?(Type::Var)
         | 
| 156 | 
            +
                      #raise if ty.is_a?(Type::Instance) && ty.klass.type_params.size > 1
         | 
| 154 157 | 
             
                      raise "Array cannot be pushed to the stack" if ty.is_a?(Type::Array)
         | 
| 155 158 | 
             
                      raise "Hash cannot be pushed to the stack" if ty.is_a?(Type::Hash)
         | 
| 156 159 | 
             
                    end
         | 
| @@ -249,6 +252,8 @@ module TypeProf | |
| 249 252 | 
             
                  @rbs_reader = RBSReader.new
         | 
| 250 253 |  | 
| 251 254 | 
             
                  @terminated = false
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                  @anonymous_struct_gen_id = 0
         | 
| 252 257 | 
             
                end
         | 
| 253 258 |  | 
| 254 259 | 
             
                attr_reader :return_envs, :loaded_features, :rbs_reader
         | 
| @@ -293,20 +298,11 @@ module TypeProf | |
| 293 298 | 
             
                  attr_reader :kind, :superclass, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
         | 
| 294 299 | 
             
                  attr_accessor :name, :klass_obj
         | 
| 295 300 |  | 
| 296 | 
            -
                  def include_module(mod, absolute_path)
         | 
| 297 | 
            -
                    # XXX: need to check if mod is already included by the ancestors?
         | 
| 298 | 
            -
                    absolute_paths = @modules[false][mod]
         | 
| 299 | 
            -
                    unless absolute_paths
         | 
| 300 | 
            -
                      @modules[false][mod] = absolute_paths = Utils::MutableSet.new
         | 
| 301 | 
            -
                    end
         | 
| 302 | 
            -
                    absolute_paths << absolute_path
         | 
| 303 | 
            -
                  end
         | 
| 304 | 
            -
             | 
| 305 | 
            -
                  def extend_module(mod, absolute_path)
         | 
| 301 | 
            +
                  def include_module(mod, singleton, absolute_path)
         | 
| 306 302 | 
             
                    # XXX: need to check if mod is already included by the ancestors?
         | 
| 307 | 
            -
                    absolute_paths = @modules[ | 
| 303 | 
            +
                    absolute_paths = @modules[singleton][mod]
         | 
| 308 304 | 
             
                    unless absolute_paths
         | 
| 309 | 
            -
                      @modules[ | 
| 305 | 
            +
                      @modules[singleton][mod] = absolute_paths = Utils::MutableSet.new
         | 
| 310 306 | 
             
                    end
         | 
| 311 307 | 
             
                    absolute_paths << absolute_path
         | 
| 312 308 | 
             
                  end
         | 
| @@ -353,7 +349,7 @@ module TypeProf | |
| 353 349 | 
             
                  end
         | 
| 354 350 | 
             
                end
         | 
| 355 351 |  | 
| 356 | 
            -
                def include_module(including_mod, included_mod, absolute_path)
         | 
| 352 | 
            +
                def include_module(including_mod, included_mod, singleton, absolute_path)
         | 
| 357 353 | 
             
                  return if included_mod == Type.any
         | 
| 358 354 |  | 
| 359 355 | 
             
                  including_mod = @class_defs[including_mod.idx]
         | 
| @@ -361,7 +357,7 @@ module TypeProf | |
| 361 357 | 
             
                    if included_mod.is_a?(Type::Class)
         | 
| 362 358 | 
             
                      included_mod = @class_defs[included_mod.idx]
         | 
| 363 359 | 
             
                      if included_mod && included_mod.kind == :module
         | 
| 364 | 
            -
                        including_mod.include_module(included_mod, absolute_path)
         | 
| 360 | 
            +
                        including_mod.include_module(included_mod, singleton, absolute_path)
         | 
| 365 361 | 
             
                      else
         | 
| 366 362 | 
             
                        warn "including something that is not a module"
         | 
| 367 363 | 
             
                      end
         | 
| @@ -369,20 +365,6 @@ module TypeProf | |
| 369 365 | 
             
                  end
         | 
| 370 366 | 
             
                end
         | 
| 371 367 |  | 
| 372 | 
            -
                def extend_module(extending_mod, extended_mod, absolute_path)
         | 
| 373 | 
            -
                  extending_mod = @class_defs[extending_mod.idx]
         | 
| 374 | 
            -
                  extended_mod.each_child do |extended_mod|
         | 
| 375 | 
            -
                    if extended_mod.is_a?(Type::Class)
         | 
| 376 | 
            -
                      extended_mod = @class_defs[extended_mod.idx]
         | 
| 377 | 
            -
                      if extended_mod && extended_mod.kind == :module
         | 
| 378 | 
            -
                        extending_mod.extend_module(extended_mod, absolute_path)
         | 
| 379 | 
            -
                      else
         | 
| 380 | 
            -
                        warn "extending something that is not a module"
         | 
| 381 | 
            -
                      end
         | 
| 382 | 
            -
                    end
         | 
| 383 | 
            -
                  end
         | 
| 384 | 
            -
                end
         | 
| 385 | 
            -
             | 
| 386 368 | 
             
                def cbase_path(cbase)
         | 
| 387 369 | 
             
                  cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
         | 
| 388 370 | 
             
                end
         | 
| @@ -417,8 +399,9 @@ module TypeProf | |
| 417 399 |  | 
| 418 400 | 
             
                  idx = @class_defs.size
         | 
| 419 401 | 
             
                  superclass = Type::Builtin[:struct]
         | 
| 420 | 
            -
                   | 
| 421 | 
            -
                   | 
| 402 | 
            +
                  name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
         | 
| 403 | 
            +
                  @class_defs[idx] = ClassDef.new(:class, [name], superclass.idx, ep.ctx.iseq.absolute_path)
         | 
| 404 | 
            +
                  klass = Type::Class.new(:class, idx, [], superclass, name)
         | 
| 422 405 | 
             
                  @class_defs[idx].klass_obj = klass
         | 
| 423 406 |  | 
| 424 407 | 
             
                  @struct_defs[ep] = klass
         | 
| @@ -572,9 +555,7 @@ module TypeProf | |
| 572 555 |  | 
| 573 556 | 
             
                  ret_ty = @return_values[callee_ctx] ||= Type.bot
         | 
| 574 557 | 
             
                  if ret_ty != Type.bot
         | 
| 575 | 
            -
                     | 
| 576 | 
            -
                      ctn[ret_ty, caller_ep, @return_envs[caller_ep]]
         | 
| 577 | 
            -
                    end
         | 
| 558 | 
            +
                    ctn[ret_ty, caller_ep, @return_envs[caller_ep]]
         | 
| 578 559 | 
             
                  end
         | 
| 579 560 | 
             
                end
         | 
| 580 561 |  | 
| @@ -632,7 +613,7 @@ module TypeProf | |
| 632 613 | 
             
                    entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new)
         | 
| 633 614 | 
             
                    if ep
         | 
| 634 615 | 
             
                      if entry.rbs_declared
         | 
| 635 | 
            -
                         | 
| 616 | 
            +
                        unless Type.match?(ty, entry.type)
         | 
| 636 617 | 
             
                          scratch.warn(ep, "inconsistent assignment to RBS-declared global variable")
         | 
| 637 618 | 
             
                          return
         | 
| 638 619 | 
             
                        end
         | 
| @@ -651,6 +632,7 @@ module TypeProf | |
| 651 632 | 
             
                end
         | 
| 652 633 |  | 
| 653 634 | 
             
                def get_ivar(recv)
         | 
| 635 | 
            +
                  recv = recv.base_type while recv.respond_to?(:base_type)
         | 
| 654 636 | 
             
                  case recv
         | 
| 655 637 | 
             
                  when Type::Class
         | 
| 656 638 | 
             
                    [@class_defs[recv.idx], true]
         | 
| @@ -884,26 +866,41 @@ module TypeProf | |
| 884 866 | 
             
                def pend_method_execution(iseq, meth, recv, mid, cref)
         | 
| 885 867 | 
             
                  ctx = Context.new(iseq, cref, mid)
         | 
| 886 868 | 
             
                  ep = ExecutionPoint.new(ctx, 0, nil)
         | 
| 887 | 
            -
                  locals = [Type. | 
| 888 | 
            -
             | 
| 889 | 
            -
                   | 
| 869 | 
            +
                  locals = [Type.nil] * iseq.locals.size
         | 
| 870 | 
            +
             | 
| 871 | 
            +
                  fargs_format = iseq.fargs_format
         | 
| 872 | 
            +
                  lead_num = fargs_format[:lead_num] || 0
         | 
| 873 | 
            +
                  post_num = fargs_format[:post_num] || 0
         | 
| 874 | 
            +
                  post_index = fargs_format[:post_start]
         | 
| 875 | 
            +
                  rest_index = fargs_format[:rest_start]
         | 
| 876 | 
            +
                  keyword = fargs_format[:keyword]
         | 
| 877 | 
            +
                  kw_index = fargs_format[:kwbits] - keyword.size if keyword
         | 
| 878 | 
            +
                  kwrest_index = fargs_format[:kwrest]
         | 
| 879 | 
            +
                  block_index = fargs_format[:block_start]
         | 
| 880 | 
            +
                  opt = fargs_format[:opt] || [0]
         | 
| 881 | 
            +
             | 
| 882 | 
            +
                  (lead_num + opt.size - 1).times {|i| locals[i] = Type.any }
         | 
| 883 | 
            +
                  post_num.times {|i| locals[i + post_index] = Type.any } if post_index
         | 
| 884 | 
            +
                  locals[rest_index] = Type.any if rest_index
         | 
| 890 885 | 
             
                  if keyword
         | 
| 891 | 
            -
                    kw_start = iseq.fargs_format[:kwbits]
         | 
| 892 | 
            -
                    kw_start -= iseq.fargs_format[:keyword].size if kw_start
         | 
| 893 886 | 
             
                    keyword.each_with_index do |kw, i|
         | 
| 894 887 | 
             
                      case
         | 
| 895 888 | 
             
                      when kw.is_a?(Symbol) # required keyword
         | 
| 889 | 
            +
                        locals[kw_index + i] = Type.any
         | 
| 896 890 | 
             
                      when kw.size == 2 # optional keyword (default value is a literal)
         | 
| 897 891 | 
             
                        _key, default_ty = *kw
         | 
| 898 892 | 
             
                        default_ty = Type.guess_literal_type(default_ty)
         | 
| 899 | 
            -
                        default_ty = default_ty. | 
| 900 | 
            -
                        locals[ | 
| 893 | 
            +
                        default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
         | 
| 894 | 
            +
                        locals[kw_index + i] = default_ty.union(Type.any)
         | 
| 901 895 | 
             
                      else # optional keyword (default value is an expression)
         | 
| 896 | 
            +
                        locals[kw_index + i] = Type.any
         | 
| 902 897 | 
             
                      end
         | 
| 903 898 | 
             
                    end
         | 
| 904 899 | 
             
                  end
         | 
| 900 | 
            +
                  locals[kwrest_index] = Type.any if kwrest_index
         | 
| 901 | 
            +
                  locals[block_index] = Type.nil if block_index
         | 
| 905 902 |  | 
| 906 | 
            -
                  env = Env.new(StaticEnv.new(recv, Type. | 
| 903 | 
            +
                  env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
         | 
| 907 904 |  | 
| 908 905 | 
             
                  @pending_execution[iseq] ||= [:method, [meth, ep, env]]
         | 
| 909 906 | 
             
                end
         | 
| @@ -986,7 +983,7 @@ module TypeProf | |
| 986 983 | 
             
                        when kw.size == 2 # optional keyword (default value is a literal)
         | 
| 987 984 | 
             
                          key, default_ty = *kw
         | 
| 988 985 | 
             
                          default_ty = Type.guess_literal_type(default_ty)
         | 
| 989 | 
            -
                          default_ty = default_ty. | 
| 986 | 
            +
                          default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
         | 
| 990 987 | 
             
                          req = false
         | 
| 991 988 | 
             
                        else # optional keyword (default value is an expression)
         | 
| 992 989 | 
             
                          key, = kw
         | 
| @@ -1029,7 +1026,17 @@ module TypeProf | |
| 1029 1026 | 
             
                    ty = Type::Literal.new(str, Type::Instance.new(Type::Builtin[:str]))
         | 
| 1030 1027 | 
             
                    env = env.push(ty)
         | 
| 1031 1028 | 
             
                  when :putself
         | 
| 1032 | 
            -
                     | 
| 1029 | 
            +
                    ty = env.static_env.recv_ty
         | 
| 1030 | 
            +
                    if ty.is_a?(Type::Instance)
         | 
| 1031 | 
            +
                      klass = ty.klass
         | 
| 1032 | 
            +
                      if klass.type_params.size >= 1
         | 
| 1033 | 
            +
                        ty = Type::ContainerType.create_empty_instance(klass)
         | 
| 1034 | 
            +
                        env, ty = localize_type(ty, env, ep, AllocationSite.new(ep))
         | 
| 1035 | 
            +
                      else
         | 
| 1036 | 
            +
                        ty = Type::Instance.new(klass)
         | 
| 1037 | 
            +
                      end
         | 
| 1038 | 
            +
                      env, ty = localize_type(ty, env, ep)
         | 
| 1039 | 
            +
                    end
         | 
| 1033 1040 | 
             
                    env = env.push(ty)
         | 
| 1034 1041 | 
             
                  when :newarray, :newarraykwsplat
         | 
| 1035 1042 | 
             
                    len, = operands
         | 
| @@ -1128,35 +1135,29 @@ module TypeProf | |
| 1128 1135 | 
             
                      else
         | 
| 1129 1136 | 
             
                        if existing_klass != Type.any
         | 
| 1130 1137 | 
             
                          error(ep, "the class \"#{ id }\" is #{ existing_klass.screen_name(self) }")
         | 
| 1131 | 
            -
                          id = :"#{ id }(dummy)"
         | 
| 1132 1138 | 
             
                        end
         | 
| 1133 | 
            -
                         | 
| 1134 | 
            -
             | 
| 1135 | 
            -
             | 
| 1136 | 
            -
             | 
| 1137 | 
            -
             | 
| 1138 | 
            -
                             | 
| 1139 | 
            -
             | 
| 1140 | 
            -
                             | 
| 1141 | 
            -
             | 
| 1142 | 
            -
             | 
| 1143 | 
            -
                             | 
| 1144 | 
            -
                              superclass = Type::Builtin[:obj]
         | 
| 1145 | 
            -
                            elsif superclass.is_a?(Type::Instance)
         | 
| 1146 | 
            -
                              warn(ep, "superclass is an instance; Object is used instead")
         | 
| 1147 | 
            -
                              superclass = Type::Builtin[:obj]
         | 
| 1148 | 
            -
                            else
         | 
| 1149 | 
            -
                              warn(ep, "superclass is not a class; Object is used instead")
         | 
| 1150 | 
            -
                              superclass = Type::Builtin[:obj]
         | 
| 1151 | 
            -
                            end
         | 
| 1152 | 
            -
                          else # module
         | 
| 1153 | 
            -
                            superclass = nil
         | 
| 1154 | 
            -
                          end
         | 
| 1155 | 
            -
                          if cbase == Type.any
         | 
| 1156 | 
            -
                            klass = Type.any
         | 
| 1139 | 
            +
                        if type == :class
         | 
| 1140 | 
            +
                          if superclass.is_a?(Type::Class)
         | 
| 1141 | 
            +
                            # okay
         | 
| 1142 | 
            +
                          elsif superclass == Type.any
         | 
| 1143 | 
            +
                            warn(ep, "superclass is any; Object is used instead")
         | 
| 1144 | 
            +
                            superclass = Type::Builtin[:obj]
         | 
| 1145 | 
            +
                          elsif superclass == Type.nil
         | 
| 1146 | 
            +
                            superclass = Type::Builtin[:obj]
         | 
| 1147 | 
            +
                          elsif superclass.is_a?(Type::Instance)
         | 
| 1148 | 
            +
                            warn(ep, "superclass is an instance; Object is used instead")
         | 
| 1149 | 
            +
                            superclass = Type::Builtin[:obj]
         | 
| 1157 1150 | 
             
                          else
         | 
| 1158 | 
            -
                             | 
| 1151 | 
            +
                            warn(ep, "superclass is not a class; Object is used instead")
         | 
| 1152 | 
            +
                            superclass = Type::Builtin[:obj]
         | 
| 1159 1153 | 
             
                          end
         | 
| 1154 | 
            +
                        else # module
         | 
| 1155 | 
            +
                          superclass = nil
         | 
| 1156 | 
            +
                        end
         | 
| 1157 | 
            +
                        if cbase == Type.any
         | 
| 1158 | 
            +
                          klass = Type.any
         | 
| 1159 | 
            +
                        else
         | 
| 1160 | 
            +
                          klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
         | 
| 1160 1161 | 
             
                        end
         | 
| 1161 1162 | 
             
                      end
         | 
| 1162 1163 | 
             
                      singleton = false
         | 
| @@ -1700,15 +1701,27 @@ module TypeProf | |
| 1700 1701 | 
             
                    end
         | 
| 1701 1702 |  | 
| 1702 1703 | 
             
                  when :checktype
         | 
| 1703 | 
            -
                     | 
| 1704 | 
            -
                     | 
| 1705 | 
            -
                     | 
| 1706 | 
            -
                     | 
| 1707 | 
            -
                     | 
| 1708 | 
            -
                    if res
         | 
| 1709 | 
            -
                      ty = Type::Instance.new(Type::Builtin[:true])
         | 
| 1704 | 
            +
                    kind, = operands
         | 
| 1705 | 
            +
                    case kind
         | 
| 1706 | 
            +
                    when 5 then klass = :str  # T_STRING
         | 
| 1707 | 
            +
                    when 7 then klass = :ary  # T_ARRAY
         | 
| 1708 | 
            +
                    when 8 then klass = :hash # T_HASH
         | 
| 1710 1709 | 
             
                    else
         | 
| 1711 | 
            -
                       | 
| 1710 | 
            +
                      raise NotImplementedError
         | 
| 1711 | 
            +
                    end
         | 
| 1712 | 
            +
                    env, (val,) = env.pop(1)
         | 
| 1713 | 
            +
                    ty = Type.bot
         | 
| 1714 | 
            +
                    val.each_child do |val|
         | 
| 1715 | 
            +
                    #globalize_type(val, env, ep).each_child_global do |val|
         | 
| 1716 | 
            +
                      val = val.base_type while val.respond_to?(:base_type)
         | 
| 1717 | 
            +
                      case val
         | 
| 1718 | 
            +
                      when Type::Instance.new(Type::Builtin[klass])
         | 
| 1719 | 
            +
                        ty = ty.union(Type::Instance.new(Type::Builtin[:true]))
         | 
| 1720 | 
            +
                      when Type.any
         | 
| 1721 | 
            +
                        ty = Type.bool
         | 
| 1722 | 
            +
                      else
         | 
| 1723 | 
            +
                        ty = ty.union(Type::Instance.new(Type::Builtin[:false]))
         | 
| 1724 | 
            +
                      end
         | 
| 1712 1725 | 
             
                    end
         | 
| 1713 1726 | 
             
                    env = env.push(ty)
         | 
| 1714 1727 | 
             
                  else
         | 
| @@ -1946,7 +1959,7 @@ module TypeProf | |
| 1946 1959 | 
             
                        end
         | 
| 1947 1960 | 
             
                      end
         | 
| 1948 1961 |  | 
| 1949 | 
            -
                      @block_to_ctx[blk.block_body] | 
| 1962 | 
            +
                      @block_to_ctx[blk.block_body]&.each do |blk_ctx|
         | 
| 1950 1963 | 
             
                        ret_ty = ret_ty.union(@return_values[blk_ctx]) if @return_values[blk_ctx]
         | 
| 1951 1964 | 
             
                      end
         | 
| 1952 1965 | 
             
                    end
         | 
    
        data/lib/typeprof/arguments.rb
    CHANGED
    
    | @@ -25,7 +25,7 @@ module TypeProf | |
| 25 25 | 
             
                  self
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| 28 | 
            -
                def consistent_with_method_signature?(msig | 
| 28 | 
            +
                def consistent_with_method_signature?(msig)
         | 
| 29 29 | 
             
                  aargs = @lead_tys.dup
         | 
| 30 30 |  | 
| 31 31 | 
             
                  # aargs: lead_tys, rest_ty
         | 
| @@ -36,53 +36,61 @@ module TypeProf | |
| 36 36 | 
             
                    (lower_bound..upper_bound).each do |n|
         | 
| 37 37 | 
             
                      # BUG: @rest_ty is an Array, so need to squash
         | 
| 38 38 | 
             
                      tmp_aargs = ActualArguments.new(@lead_tys + [@rest_ty] * n, nil, @kw_tys, @blk_ty)
         | 
| 39 | 
            -
                       | 
| 40 | 
            -
             | 
| 41 | 
            -
                      end
         | 
| 39 | 
            +
                      subst = tmp_aargs.consistent_with_method_signature?(msig) # XXX: wrong subst handling in the loop!
         | 
| 40 | 
            +
                      return subst if subst
         | 
| 42 41 | 
             
                    end
         | 
| 43 | 
            -
                    return  | 
| 42 | 
            +
                    return nil
         | 
| 44 43 | 
             
                  end
         | 
| 45 44 |  | 
| 45 | 
            +
                  subst = {}
         | 
| 46 46 | 
             
                  if msig.rest_ty
         | 
| 47 | 
            -
                    return  | 
| 47 | 
            +
                    return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
         | 
| 48 48 | 
             
                    aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
         | 
| 49 | 
            -
                      return  | 
| 49 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 50 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 50 51 | 
             
                    end
         | 
| 51 52 | 
             
                    aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
         | 
| 52 | 
            -
                      return  | 
| 53 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 54 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 53 55 | 
             
                    end
         | 
| 54 56 | 
             
                    msig.opt_tys.each do |farg|
         | 
| 55 57 | 
             
                      aarg = aargs.shift
         | 
| 56 | 
            -
                      return  | 
| 58 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 59 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 57 60 | 
             
                    end
         | 
| 58 61 | 
             
                    aargs.each do |aarg|
         | 
| 59 | 
            -
                      return  | 
| 62 | 
            +
                      return nil unless subst2 = Type.match?(aarg, msig.rest_ty)
         | 
| 63 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 60 64 | 
             
                    end
         | 
| 61 65 | 
             
                  else
         | 
| 62 | 
            -
                    return  | 
| 63 | 
            -
                    return  | 
| 66 | 
            +
                    return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size
         | 
| 67 | 
            +
                    return nil if aargs.size > msig.lead_tys.size + msig.post_tys.size + msig.opt_tys.size
         | 
| 64 68 | 
             
                    aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg|
         | 
| 65 | 
            -
                      return  | 
| 69 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 70 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 66 71 | 
             
                    end
         | 
| 67 72 | 
             
                    aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg|
         | 
| 68 | 
            -
                      return  | 
| 73 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 74 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 69 75 | 
             
                    end
         | 
| 70 76 | 
             
                    aargs.zip(msig.opt_tys) do |aarg, farg|
         | 
| 71 | 
            -
                      return  | 
| 77 | 
            +
                      return nil unless subst2 = Type.match?(aarg, farg)
         | 
| 78 | 
            +
                      subst = Type.merge_substitution(subst, subst2)
         | 
| 72 79 | 
             
                    end
         | 
| 73 80 | 
             
                  end
         | 
| 74 81 | 
             
                  # XXX: msig.keyword_tys
         | 
| 75 82 |  | 
| 76 83 | 
             
                  case msig.blk_ty
         | 
| 77 84 | 
             
                  when Type::Proc
         | 
| 78 | 
            -
                    return  | 
| 85 | 
            +
                    return nil if @blk_ty == Type.nil
         | 
| 79 86 | 
             
                  when Type.nil
         | 
| 80 | 
            -
                    return  | 
| 87 | 
            +
                    return nil if @blk_ty != Type.nil
         | 
| 81 88 | 
             
                  when Type::Any
         | 
| 82 89 | 
             
                  else
         | 
| 83 90 | 
             
                    raise "unknown type of formal block signature"
         | 
| 84 91 | 
             
                  end
         | 
| 85 | 
            -
             | 
| 92 | 
            +
             | 
| 93 | 
            +
                  subst
         | 
| 86 94 | 
             
                end
         | 
| 87 95 |  | 
| 88 96 | 
             
                def argument_error(given, exp_lower, exp_upper)
         | 
| @@ -345,7 +353,7 @@ module TypeProf | |
| 345 353 | 
             
                      when kw.size == 2 # optional keyword (default value is a literal)
         | 
| 346 354 | 
             
                        key, default_ty = *kw
         | 
| 347 355 | 
             
                        default_ty = Type.guess_literal_type(default_ty)
         | 
| 348 | 
            -
                        default_ty = default_ty. | 
| 356 | 
            +
                        default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal)
         | 
| 349 357 | 
             
                        req = false
         | 
| 350 358 | 
             
                      else # optional keyword (default value is an expression)
         | 
| 351 359 | 
             
                        key, = kw
         |