class Steep::Interface::Block

def +(other)

def +(other)
  optional = self.optional? || other.optional?
  type = Function.new(
    params: self.type.params && other.type.params ? self.type.params + other.type.params : nil,
    return_type: AST::Types::Union.build(types: [self.type.return_type, other.type.return_type]),
    location: nil
  )
  self_types = [self.self_type, other.self_type].compact
  self.class.new(
    type: type,
    optional: optional,
    self_type:
      unless self_types.empty?
        AST::Types::Union.build(types: self_types)
      end
  )
end

def ==(other)

def ==(other)
  other.is_a?(self.class) && other.type == type && other.optional == optional && other.self_type == self_type
end

def closed?

def closed?
  type.closed?
end

def free_variables()

def free_variables()
  @fvs ||= type.free_variables + (self_type&.free_variables || Set[])
end

def hash

def hash
  type.hash ^ optional.hash ^ self_type.hash
end

def initialize(type:, optional:, self_type:)

def initialize(type:, optional:, self_type:)
  @type = type
  @optional = optional
  @self_type = self_type
end

def map_type(&block)

def map_type(&block)
  self.class.new(
    type: type.map_type(&block),
    self_type: self_type&.map_type(&block),
    optional: optional
  )
end

def optional?

def optional?
  @optional
end

def required?

def required?
  !optional?
end

def subst(s)

def subst(s)
  ty = type.subst(s)
  st = self_type.subst(s) if self_type
  if ty == type && st == self_type
    self
  else
    self.class.new(type: ty, self_type: st, optional: optional)
  end
end

def to_optional

def to_optional
  self.class.new(
    type: type,
    self_type: self_type,
    optional: true
  )
end

def to_proc_type

def to_proc_type
  proc = AST::Types::Proc.new(type: type, self_type: self_type, block: nil)
  if optional?
    AST::Types::Union.build(types: [proc, AST::Builtin.nil_type])
  else
    proc
  end
end

def to_s

def to_s
  self_binding = self_type ? "[self: #{self_type}] " : ""
  "#{optional? ? "?" : ""}{ #{type.params} #{self_binding}-> #{type.return_type} }"
end