Repository: carbon-language/carbon-lang
File: toolchain/check/type_structure.cpp (C++)

Code before:
// type.
class TypeStructureBuilder {
 public:
  explicit TypeStructureBuilder(Context& context) : context_(context) {}

  auto Run(SemIR::InstId self_inst_id,
           SemIR::SpecificInterface interface_constraint) -> TypeStructure {
    CARBON_CHECK(work_list_.empty());

    position_ = 0;
    first_symbolic_distance_ = TypeStructure::InfiniteDistance;
    structure_.clear();

    // The self type comes first in the type structure, so we push it last, as
    // the queue works from the back.
    Push(interface_constraint);

    auto maybe_self_type_id = TryGetInstIdAsTypeId(self_inst_id);
    if (std::holds_alternative<SemIR::TypeId>(maybe_self_type_id)) {
      auto self_type_id = std::get<SemIR::TypeId>(maybe_self_type_id);
      CARBON_CHECK(self_type_id != SemIR::TypeId::None);
      Push(self_type_id);
    } else {
      CARBON_CHECK(std::holds_alternative<SymbolicType>(maybe_self_type_id));
      Push(SymbolicType());
    }
    BuildTypeStructure();

    return TypeStructure(std::exchange(structure_, {}),
                         first_symbolic_distance_);
  }

 private:
  auto BuildTypeStructure() -> void {
    while (!work_list_.empty()) {
      auto next = work_list_.back();
      work_list_.pop_back();

      if (std::holds_alternative<CloseType>(next)) {
        auto close_type = std::get<CloseType>(next);
        switch (close_type.closing) {
          case CloseOnly:
            break;
          case CloseWithConcrete:
            ++position_;
            structure_.push_back(TypeStructure::Structural::Concrete);
            break;
          case CloseWithSymbolic:
            SetFirstSymbolic(position_);
            ++position_;
            structure_.push_back(TypeStructure::Structural::Symbolic);

Review comment (refactor):
It looks like this duplicates some of the work of `PushArgs`; would it make sense to factor out a `PushArg`?

Code after:
    }
  }

  return true;
}

// A class that builds a `TypeStructure` for an `Impl`, or an impl lookup query,
// that represents its self type and interface.
class TypeStructureBuilder {
 public:
  explicit TypeStructureBuilder(Context& context) : context_(context) {}

  auto Run(SemIR::InstId self_inst_id,
           SemIR::SpecificInterface interface_constraint) -> TypeStructure {
    CARBON_CHECK(work_list_.empty());

    first_symbolic_distance_ = TypeStructure::InfiniteDistance;
    structure_.clear();

    // The self type comes first in the type structure, so we push it last, as
    // the queue works from the back.
    Push(interface_constraint);
    PushInstId(self_inst_id);
    BuildTypeStructure();

    return TypeStructure(std::exchange(structure_, {}),
                         first_symbolic_distance_);
  }

 private:
  auto BuildTypeStructure() -> void {
    while (!work_list_.empty()) {
      auto next = work_list_.back();
      work_list_.pop_back();

      if (std::holds_alternative<CloseType>(next)) {
        AppendStructural(TypeStructure::Structural::ConcreteCloseParen);
        continue;
      }

      if (const auto* interface =
              std::get_if<SemIR::SpecificInterface>(&next)) {
        auto args = GetSpecificArgs(interface->specific_id);
        if (args.empty()) {
          AppendStructural(TypeStructure::Structural::Concrete);
        } else {
          AppendStructural(TypeStructure::Structural::ConcreteOpenParen);
          Push(CloseType());
          PushArgs(args);
        }
        continue;