Repository: carbon-language/carbon-lang
File: common/error.h (C/C++)

Code before:
  // The error message.
  std::string message_;
};

// A common base class that custom error types should derive from.
//
// This combines the ability to be printed with the ability to convert the error
// to a string and in turn to a non-customized `Error` type by rendering into a
// string.
//
// The goal is that custom error types can be used for errors that are common
// and/or would have cost to fully render the error message to a string. A
// custom type can then be used to allow custom, light-weight handling of errors
// when appropriate. But to avoid these custom types being excessively viral, we
// ensure they can be converted to normal `Error` types when needed by rendering
// fully to a string.
template <typename ErrorT>
class [[nodiscard]] ErrorBase : public Printable<ErrorT> {
 public:
  // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility): Deleted.
  ErrorBase(const ErrorBase&) = delete;

  auto ToString() const -> std::string {
    RawStringOstream s;
    static_cast<const ErrorT*>(this)->Print(s);
    return s.TakeStr();
  }

  explicit operator Error() { return Error(this->ToString()); }

 private:
  friend ErrorT;

  ErrorBase() = default;
  ErrorBase(ErrorBase&&) noexcept = default;
  auto operator=(ErrorBase&&) noexcept -> ErrorBase& = default;
};

// Holds a value of type `T`, or an `ErrorT` type explaining why the value is
// unavailable.
//
// The `ErrorT` type defaults to `Error` but can be customized where desired
// with a type that derives from `ErrorBase` above. See the documentation for
// `ErrorBase` to understand the expected contract of custom error types.
//
// This is nodiscard to enforce error handling prior to destruction.
template <typename T, typename ErrorT = Error>
class [[nodiscard]] ErrorOr {
 public:
  using ValueT = std::remove_reference_t<T>;
  static_assert(!std::is_reference_v<ErrorT>,

Review comment (suggestion):
I think `Printable::Dump` is identical, maybe you can use it directly? (assuming you want to keep the `ToString` name)

```suggestion
    return Dump();
```

Code after:
  // The error message.
  std::string message_;
};

// A common base class that custom error types should derive from.
//
// This combines the ability to be printed with the ability to convert the error
// to a string and in turn to a non-customized `Error` type by rendering into a
// string.
//
// The goal is that custom error types can be used for errors that are common
// and/or would have cost to fully render the error message to a string. A
// custom type can then be used to allow custom, light-weight handling of errors
// when appropriate. But to avoid these custom types being excessively viral, we
// ensure they can be converted to normal `Error` types when needed by rendering
// fully to a string.
template <typename ErrorT>
class [[nodiscard]] ErrorBase : public Printable<ErrorT> {
 public:
  ErrorBase(const ErrorBase&) = delete;
  auto operator=(const ErrorBase&) -> ErrorBase& = delete;

  auto ToString() const -> std::string {
    RawStringOstream os;
    static_cast<const ErrorT*>(this)->Print(os);
    return os.TakeStr();
  }
  auto ToError() const -> Error { return Error(this->ToString()); }

 protected:
  ErrorBase() = default;
  ErrorBase(ErrorBase&&) noexcept = default;
  auto operator=(ErrorBase&&) noexcept -> ErrorBase& = default;
};

// Holds a value of type `T`, or an `ErrorT` type explaining why the value is
// unavailable.
//
// The `ErrorT` type defaults to `Error` but can be customized where desired
// with a type that derives from `ErrorBase` above. See the documentation for
// `ErrorBase` to understand the expected contract of custom error types.
//
// This is nodiscard to enforce error handling prior to destruction.
template <typename T, typename ErrorT = Error>
  requires(!std::is_reference_v<ErrorT> &&
           (std::same_as<ErrorT, Error> ||
            std::derived_from<ErrorT, ErrorBase<ErrorT>>))
class [[nodiscard]] ErrorOr {
 public:
  using ValueT = std::remove_reference_t<T>;