Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/ids.h (C/C++)

Code before:
// before construction, and this allows that validation to be represented in the
// type system.
struct TypeInstId : public InstId {
  static constexpr llvm::StringLiteral Label = "type_inst";
  static const TypeInstId None;

  using InstId::InstId;

  static constexpr auto UnsafeMake(InstId id) -> TypeInstId {
    return TypeInstId(UnsafeCtor(), id);
  }

 private:
  struct UnsafeCtor {};
  explicit constexpr TypeInstId(UnsafeCtor /*unsafe*/, InstId id)
      : InstId(id) {}
};

constexpr TypeInstId TypeInstId::None = TypeInstId::UnsafeMake(InstId::None);

// An InstId whose type is known to be T. The fact it's a type must be validated
// before construction, and this allows that validation to be represented in the
// type system.
template <class T>
struct KnownInstId : public InstId {
  // FIXME: static constexpr llvm::StringLiteral Label = "known_inst";
  static const KnownInstId None;

  using InstId::InstId;

  static constexpr auto UnsafeMake(InstId id) -> KnownInstId {
    return KnownInstId(UnsafeCtor(), id);
  }

 private:
  struct UnsafeCtor {};
  explicit constexpr KnownInstId(UnsafeCtor /*unsafe*/, InstId id)
      : InstId(id) {}
};

template <class T>
constexpr KnownInstId<T> KnownInstId<T>::None =
    KnownInstId<T>::UnsafeMake(InstId::None);

// An ID of an instruction that is referenced absolutely by another instruction.
// This should only be used as the type of a field within a typed instruction
// class.
//
// When a typed instruction has a field of this type, that field represents an
// absolute reference to another instruction that typically resides in a
// different entity. This behaves in most respects like an InstId field, but

Review comment (suggestion):
Do you intend to do something with this? (Is the one in `TypeInstId` used for anything? My clangd instance doesn't think so.)

Code after:
// before construction, and this allows that validation to be represented in the
// type system.
struct TypeInstId : public InstId {
  static const TypeInstId None;

  using InstId::InstId;

  static constexpr auto UnsafeMake(InstId id) -> TypeInstId {
    return TypeInstId(UnsafeCtor(), id);
  }

 private:
  struct UnsafeCtor {};
  explicit constexpr TypeInstId(UnsafeCtor /*unsafe*/, InstId id)
      : InstId(id) {}
};

constexpr TypeInstId TypeInstId::None = TypeInstId::UnsafeMake(InstId::None);

// An InstId whose type is known to be T. The fact it's a type must be validated
// before construction, and this allows that validation to be represented in the
// type system.
//
// Unlike TypeInstId, this type can *not* be an operand in instructions, since
// being a template prevents it from being used in non-generic contexts such as
// switches.
template <class T>
struct KnownInstId : public InstId {
  static const KnownInstId None;

  using InstId::InstId;

  static constexpr auto UnsafeMake(InstId id) -> KnownInstId {
    return KnownInstId(UnsafeCtor(), id);
  }

 private:
  struct UnsafeCtor {};
  explicit constexpr KnownInstId(UnsafeCtor /*unsafe*/, InstId id)
      : InstId(id) {}
};

template <class T>
constexpr KnownInstId<T> KnownInstId<T>::None =
    KnownInstId<T>::UnsafeMake(InstId::None);

// An ID of an instruction that is referenced absolutely by another instruction.
// This should only be used as the type of a field within a typed instruction
// class.
//
// When a typed instruction has a field of this type, that field represents an