class Steep::Subtyping::Check

def check(relation, constraints:, self_type:, assumption: Set.new, trace: Trace.new)

def check(relation, constraints:, self_type:, assumption: Set.new, trace: Trace.new)
  Steep.logger.tagged "#{relation.sub_type} <: #{relation.super_type}" do
    prefix = trace.size
    cached = cache[[relation, self_type]]
    if cached && constraints.empty?
      if cached.success?
        cached
      else
        cached.merge_trace(trace)
      end
    else
      if assumption.member?(relation)
        success(constraints: constraints)
      else
        assumption = assumption + Set[relation]
        check0(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints).tap do |result|
          result = result.else do |failure|
            failure.drop(prefix)
          end
          Steep.logger.debug "result=#{result.class}"
          cache[[relation, self_type]] = result if cacheable?(relation)
        end
      end
    end
  end
end