class TypeProf::Type::Union

Attributes

elems[R]
types[R]

Public Class Methods

create(tys, elems) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 222
def self.create(tys, elems)
  if tys.size == 1 && !elems
    tys.each {|ty| return ty }
  elsif tys.size == 0
    if elems && elems.size == 1
      (container_kind, base_type), nelems = elems.first
      # container_kind = Type::Array or Type::Hash
      container_kind.new(nelems, base_type)
    else
      new(tys, elems)
    end
  else
    class_instances = []
    non_class_instances = []
    degenerated = false
    tys.each do |ty|
      if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class
        class_instances << ty
        degenerated = true if ty.include_subclasses
      else
        non_class_instances << ty
      end
    end
    if (Config.current.options[:union_width_limit] >= 2 && class_instances.size >= Config.current.options[:union_width_limit]) || (degenerated && class_instances.size >= 2)
      create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems)
    else
      new(tys, elems)
    end
  end
end
new(tys, elems) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 253
def initialize(tys, elems)
  raise unless tys.is_a?(Utils::Set)
  @types = tys # Set

  # invariant check
  local = nil
  tys.each do |ty|
    raise ty.inspect unless ty.is_a?(Type)
    local = true if ty.is_a?(Local)
  end
  raise if local && elems

  @elems = elems
  raise elems.inspect if elems && !elems.is_a?(::Hash)
end

Public Instance Methods

consistent?(_other) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 388
def consistent?(_other)
  raise "should not be called"
end
each_child(&blk) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 289
def each_child(&blk) # local
  @types.each(&blk)
  raise if @elems
end
each_child_global() { |container_kind| ... } click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 294
def each_child_global(&blk)
  @types.each(&blk)
  @elems&.each do |(container_kind, base_type), elems|
    yield container_kind.new(elems, base_type)
  end
end
each_free_type_variable(&blk) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 269
def each_free_type_variable(&blk)
  each_child_global do |ty|
    ty.each_free_type_variable(&blk)
  end
end
globalize(env, visited, depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 347
def globalize(env, visited, depth)
  return Type.any if depth <= 0
  tys = Utils::Set[]
  if @elems
    # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur.
    # However, currently, ActualArguments may contain global types for flag_args_kw_splat case.
    # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments.
    #raise
  end

  elems = @elems ? @elems.dup : {}
  @types.each do |ty|
    ty = ty.globalize(env, visited, depth - 1)
    case ty
    when Type::Array, Type::Hash
      key = [ty.class, ty.base_type]
      elems[key] = union_elems(elems[key], ty.elems)
    else
      tys = tys.add(ty)
    end
  end
  elems = nil if elems.empty?

  Type::Union.create(tys, elems)
end
include_untyped?(scratch) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 415
def include_untyped?(scratch)
  @types.each do |ty|
    return true if ty.include_untyped?(scratch)
  end
  @elems&.each do |(container_kind, base_type), elems|
    return true if base_type.include_untyped?(scratch)
    return true if elems.include_untyped?(scratch)
  end
  false
end
inspect() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 301
def inspect
  a = []
  a << "Type::Union{#{ @types.to_a.map {|ty| ty.inspect }.join(", ") }"
  @elems&.each do |(container_kind, base_type), elems|
    a << ", #{ container_kind.new(elems, base_type).inspect }"
  end
  a << "}"
  a.join
end
limit_size(limit) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 275
def limit_size(limit)
  return Type.any if limit <= 0
  tys = Utils::Set[]
  @types.each do |ty|
    tys = tys.add(ty.limit_size(limit - 1))
  end
  elems = @elems&.to_h do |key, elems|
    [key, elems.limit_size(limit - 1)]
  end
  Union.new(tys, elems)
end
localize(env, alloc_site, depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 373
def localize(env, alloc_site, depth)
  return env, Type.any if depth <= 0
  tys = @types.map do |ty|
    env, ty2 = ty.localize(env, alloc_site, depth - 1)
    ty2
  end
  @elems&.each do |(container_kind, base_type), elems|
    ty = container_kind.new(elems, base_type)
    env, ty = ty.localize(env, alloc_site, depth - 1)
    tys = tys.add(ty)
  end
  ty = Union.create(tys, nil)
  return env, ty
end
screen_name(scratch) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 311
def screen_name(scratch)
  types = @types.to_a
  @elems&.each do |(container_kind, base_type), elems|
    types << container_kind.new(elems, base_type)
  end
  if types.size == 0
    "bot"
  else
    types = types.to_a
    optional = !!types.delete(Type::Instance.new(Type::Builtin[:nil]))
    bool = false
    if types.include?(Type::Instance.new(Type::Builtin[:false])) &&
       types.include?(Type::Instance.new(Type::Builtin[:true]))
      types.delete(Type::Instance.new(Type::Builtin[:false]))
      types.delete(Type::Instance.new(Type::Builtin[:true]))
      bool = true
    end
    types.delete(Type.any) unless Config.current.options[:show_untyped]
    proc_tys, types = types.partition {|ty| ty.is_a?(Proc) }
    types = types.map {|ty| ty.screen_name(scratch) }
    types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty?
    types << "bool" if bool
    types = types.sort
    if optional
      case types.size
      when 0 then "nil"
      when 1 then types.first + "?"
      else
        "(#{ types.join (" | ") })?"
      end
    else
      types.join (" | ")
    end
  end
end
substitute(subst, depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 392
def substitute(subst, depth)
  return Type.any if depth <= 0
  unions = []
  tys = Utils::Set[]
  @types.each do |ty|
    ty = ty.substitute(subst, depth - 1)
    case ty
    when Union
      unions << ty
    else
      tys = tys.add(ty)
    end
  end
  elems = @elems&.to_h do |(container_kind, base_type), elems|
    [[container_kind, base_type], elems.substitute(subst, depth - 1)]
  end
  ty = Union.create(tys, elems)
  unions.each do |ty0|
    ty = ty.union(ty0)
  end
  ty
end