aboutsummaryrefslogtreecommitdiff
path: root/third_party/abseil-cpp/absl/status
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/abseil-cpp/absl/status')
-rw-r--r--third_party/abseil-cpp/absl/status/BUILD.bazel44
-rw-r--r--third_party/abseil-cpp/absl/status/CMakeLists.txt40
-rw-r--r--third_party/abseil-cpp/absl/status/internal/status_internal.h69
-rw-r--r--third_party/abseil-cpp/absl/status/internal/statusor_internal.h396
-rw-r--r--third_party/abseil-cpp/absl/status/status.cc65
-rw-r--r--third_party/abseil-cpp/absl/status/status.h696
-rw-r--r--third_party/abseil-cpp/absl/status/status_payload_printer.cc15
-rw-r--r--third_party/abseil-cpp/absl/status/status_test.cc36
-rw-r--r--third_party/abseil-cpp/absl/status/statusor.cc103
-rw-r--r--third_party/abseil-cpp/absl/status/statusor.h770
-rw-r--r--third_party/abseil-cpp/absl/status/statusor_test.cc1847
11 files changed, 171 insertions, 3910 deletions
diff --git a/third_party/abseil-cpp/absl/status/BUILD.bazel b/third_party/abseil-cpp/absl/status/BUILD.bazel
index bae5156f4a..2b83077def 100644
--- a/third_party/abseil-cpp/absl/status/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/status/BUILD.bazel
@@ -17,6 +17,7 @@
# It will expand later to have utilities around `Status` like `StatusOr`,
# `StatusBuilder` and macros.
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -25,12 +26,11 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "status",
srcs = [
- "internal/status_internal.h",
"status.cc",
"status_payload_printer.cc",
],
@@ -40,14 +40,12 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
deps = [
- "//absl/base:atomic_hook",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/container:inlined_vector",
"//absl/debugging:stacktrace",
"//absl/debugging:symbolize",
- "//absl/functional:function_ref",
"//absl/strings",
"//absl/strings:cord",
"//absl/strings:str_format",
@@ -65,41 +63,3 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
-
-cc_library(
- name = "statusor",
- srcs = [
- "internal/statusor_internal.h",
- "statusor.cc",
- ],
- hdrs = [
- "statusor.h",
- ],
- copts = ABSL_DEFAULT_COPTS,
- deps = [
- ":status",
- "//absl/base",
- "//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
- "//absl/meta:type_traits",
- "//absl/strings",
- "//absl/types:variant",
- "//absl/utility",
- ],
-)
-
-cc_test(
- name = "statusor_test",
- size = "small",
- srcs = ["statusor_test.cc"],
- deps = [
- ":status",
- ":statusor",
- "//absl/base",
- "//absl/memory",
- "//absl/strings",
- "//absl/types:any",
- "//absl/utility",
- "@com_google_googletest//:gtest_main",
- ],
-)
diff --git a/third_party/abseil-cpp/absl/status/CMakeLists.txt b/third_party/abseil-cpp/absl/status/CMakeLists.txt
index f107c85b1c..f05cee5e95 100644
--- a/third_party/abseil-cpp/absl/status/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/status/CMakeLists.txt
@@ -19,17 +19,14 @@ absl_cc_library(
HDRS
"status.h"
SRCS
- "internal/status_internal.h"
"status.cc"
"status_payload_printer.h"
"status_payload_printer.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::atomic_hook
absl::config
absl::core_headers
- absl::function_ref
absl::raw_logging_internal
absl::inlined_vector
absl::stacktrace
@@ -51,40 +48,5 @@ absl_cc_test(
DEPS
absl::status
absl::strings
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- statusor
- HDRS
- "statusor.h"
- SRCS
- "statusor.cc"
- "internal/statusor_internal.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base
- absl::status
- absl::core_headers
- absl::raw_logging_internal
- absl::type_traits
- absl::strings
- absl::utility
- absl::variant
- PUBLIC
-)
-
-absl_cc_test(
- NAME
- statusor_test
- SRCS
- "statusor_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::status
- absl::statusor
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/status/internal/status_internal.h b/third_party/abseil-cpp/absl/status/internal/status_internal.h
deleted file mode 100644
index ac12940a6d..0000000000
--- a/third_party/abseil-cpp/absl/status/internal/status_internal.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
-#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
-
-#include <string>
-
-#include "absl/container/inlined_vector.h"
-#include "absl/strings/cord.h"
-
-#ifndef SWIG
-// Disabled for SWIG as it doesn't parse attributes correctly.
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-// Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs
-// as part of a class definitions (b/6995610), so we use a forward declaration.
-class ABSL_MUST_USE_RESULT Status;
-ABSL_NAMESPACE_END
-} // namespace absl
-#endif // !SWIG
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-enum class StatusCode : int;
-
-namespace status_internal {
-
-// Container for status payloads.
-struct Payload {
- std::string type_url;
- absl::Cord payload;
-};
-
-using Payloads = absl::InlinedVector<Payload, 1>;
-
-// Reference-counted representation of Status data.
-struct StatusRep {
- StatusRep(absl::StatusCode code_arg, absl::string_view message_arg,
- std::unique_ptr<status_internal::Payloads> payloads_arg)
- : ref(int32_t{1}),
- code(code_arg),
- message(message_arg),
- payloads(std::move(payloads_arg)) {}
-
- std::atomic<int32_t> ref;
- absl::StatusCode code;
- std::string message;
- std::unique_ptr<status_internal::Payloads> payloads;
-};
-
-absl::StatusCode MapToLocalCode(int value);
-} // namespace status_internal
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
diff --git a/third_party/abseil-cpp/absl/status/internal/statusor_internal.h b/third_party/abseil-cpp/absl/status/internal/statusor_internal.h
deleted file mode 100644
index eaac2c0b14..0000000000
--- a/third_party/abseil-cpp/absl/status/internal/statusor_internal.h
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright 2020 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
-#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
-
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/attributes.h"
-#include "absl/meta/type_traits.h"
-#include "absl/status/status.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-template <typename T>
-class ABSL_MUST_USE_RESULT StatusOr;
-
-namespace internal_statusor {
-
-// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
-// StatusOr<T>()`.
-template <typename T, typename U, typename = void>
-struct HasConversionOperatorToStatusOr : std::false_type {};
-
-template <typename T, typename U>
-void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
-
-template <typename T, typename U>
-struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
- : std::true_type {};
-
-// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
-template <typename T, typename U>
-using IsConstructibleOrConvertibleFromStatusOr =
- absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
- std::is_constructible<T, const StatusOr<U>&>,
- std::is_constructible<T, StatusOr<U>&&>,
- std::is_constructible<T, const StatusOr<U>&&>,
- std::is_convertible<StatusOr<U>&, T>,
- std::is_convertible<const StatusOr<U>&, T>,
- std::is_convertible<StatusOr<U>&&, T>,
- std::is_convertible<const StatusOr<U>&&, T>>;
-
-// Detects whether `T` is constructible or convertible or assignable from
-// `StatusOr<U>`.
-template <typename T, typename U>
-using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
- absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
- std::is_assignable<T&, StatusOr<U>&>,
- std::is_assignable<T&, const StatusOr<U>&>,
- std::is_assignable<T&, StatusOr<U>&&>,
- std::is_assignable<T&, const StatusOr<U>&&>>;
-
-// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
-// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
-template <typename T, typename U>
-struct IsDirectInitializationAmbiguous
- : public absl::conditional_t<
- std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
- U>::value,
- std::false_type,
- IsDirectInitializationAmbiguous<
- T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
-
-template <typename T, typename V>
-struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
- : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
-
-// Checks against the constraints of the direction initialization, i.e. when
-// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
-template <typename T, typename U>
-using IsDirectInitializationValid = absl::disjunction<
- // Short circuits if T is basically U.
- std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
- absl::negation<absl::disjunction<
- std::is_same<absl::StatusOr<T>,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- std::is_same<absl::Status,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- std::is_same<absl::in_place_t,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- IsDirectInitializationAmbiguous<T, U>>>>;
-
-// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
-// is equivalent to whether all the following conditions are met:
-// 1. `U` is `StatusOr<V>`.
-// 2. `T` is constructible and assignable from `V`.
-// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
-// For example, the following code is considered ambiguous:
-// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
-// StatusOr<bool> s1 = true; // s1.ok() && s1.ValueOrDie() == true
-// StatusOr<bool> s2 = false; // s2.ok() && s2.ValueOrDie() == false
-// s1 = s2; // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
-template <typename T, typename U>
-struct IsForwardingAssignmentAmbiguous
- : public absl::conditional_t<
- std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
- U>::value,
- std::false_type,
- IsForwardingAssignmentAmbiguous<
- T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
-
-template <typename T, typename U>
-struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
- : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
-
-// Checks against the constraints of the forwarding assignment, i.e. whether
-// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
-template <typename T, typename U>
-using IsForwardingAssignmentValid = absl::disjunction<
- // Short circuits if T is basically U.
- std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
- absl::negation<absl::disjunction<
- std::is_same<absl::StatusOr<T>,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- std::is_same<absl::Status,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- std::is_same<absl::in_place_t,
- absl::remove_cv_t<absl::remove_reference_t<U>>>,
- IsForwardingAssignmentAmbiguous<T, U>>>>;
-
-class Helper {
- public:
- // Move type-agnostic error handling to the .cc.
- static void HandleInvalidStatusCtorArg(Status*);
- ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
-};
-
-// Construct an instance of T in `p` through placement new, passing Args... to
-// the constructor.
-// This abstraction is here mostly for the gcc performance fix.
-template <typename T, typename... Args>
-ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
- new (p) T(std::forward<Args>(args)...);
-}
-
-// Helper base class to hold the data and all operations.
-// We move all this to a base class to allow mixing with the appropriate
-// TraitsBase specialization.
-template <typename T>
-class StatusOrData {
- template <typename U>
- friend class StatusOrData;
-
- public:
- StatusOrData() = delete;
-
- StatusOrData(const StatusOrData& other) {
- if (other.ok()) {
- MakeValue(other.data_);
- MakeStatus();
- } else {
- MakeStatus(other.status_);
- }
- }
-
- StatusOrData(StatusOrData&& other) noexcept {
- if (other.ok()) {
- MakeValue(std::move(other.data_));
- MakeStatus();
- } else {
- MakeStatus(std::move(other.status_));
- }
- }
-
- template <typename U>
- explicit StatusOrData(const StatusOrData<U>& other) {
- if (other.ok()) {
- MakeValue(other.data_);
- MakeStatus();
- } else {
- MakeStatus(other.status_);
- }
- }
-
- template <typename U>
- explicit StatusOrData(StatusOrData<U>&& other) {
- if (other.ok()) {
- MakeValue(std::move(other.data_));
- MakeStatus();
- } else {
- MakeStatus(std::move(other.status_));
- }
- }
-
- template <typename... Args>
- explicit StatusOrData(absl::in_place_t, Args&&... args)
- : data_(std::forward<Args>(args)...) {
- MakeStatus();
- }
-
- explicit StatusOrData(const T& value) : data_(value) {
- MakeStatus();
- }
- explicit StatusOrData(T&& value) : data_(std::move(value)) {
- MakeStatus();
- }
-
- template <typename U,
- absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
- int> = 0>
- explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
- EnsureNotOk();
- }
-
- StatusOrData& operator=(const StatusOrData& other) {
- if (this == &other) return *this;
- if (other.ok())
- Assign(other.data_);
- else
- AssignStatus(other.status_);
- return *this;
- }
-
- StatusOrData& operator=(StatusOrData&& other) {
- if (this == &other) return *this;
- if (other.ok())
- Assign(std::move(other.data_));
- else
- AssignStatus(std::move(other.status_));
- return *this;
- }
-
- ~StatusOrData() {
- if (ok()) {
- status_.~Status();
- data_.~T();
- } else {
- status_.~Status();
- }
- }
-
- template <typename U>
- void Assign(U&& value) {
- if (ok()) {
- data_ = std::forward<U>(value);
- } else {
- MakeValue(std::forward<U>(value));
- status_ = OkStatus();
- }
- }
-
- template <typename U>
- void AssignStatus(U&& v) {
- Clear();
- status_ = static_cast<absl::Status>(std::forward<U>(v));
- EnsureNotOk();
- }
-
- bool ok() const { return status_.ok(); }
-
- protected:
- // status_ will always be active after the constructor.
- // We make it a union to be able to initialize exactly how we need without
- // waste.
- // Eg. in the copy constructor we use the default constructor of Status in
- // the ok() path to avoid an extra Ref call.
- union {
- Status status_;
- };
-
- // data_ is active iff status_.ok()==true
- struct Dummy {};
- union {
- // When T is const, we need some non-const object we can cast to void* for
- // the placement new. dummy_ is that object.
- Dummy dummy_;
- T data_;
- };
-
- void Clear() {
- if (ok()) data_.~T();
- }
-
- void EnsureOk() const {
- if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
- }
-
- void EnsureNotOk() {
- if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
- }
-
- // Construct the value (ie. data_) through placement new with the passed
- // argument.
- template <typename... Arg>
- void MakeValue(Arg&&... arg) {
- internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
- }
-
- // Construct the status (ie. status_) through placement new with the passed
- // argument.
- template <typename... Args>
- void MakeStatus(Args&&... args) {
- internal_statusor::PlacementNew<Status>(&status_,
- std::forward<Args>(args)...);
- }
-};
-
-// Helper base classes to allow implicitly deleted constructors and assignment
-// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
-// the copy constructor when T is not copy constructible and `StatusOr` will
-// inherit that behavior implicitly.
-template <typename T, bool = std::is_copy_constructible<T>::value>
-struct CopyCtorBase {
- CopyCtorBase() = default;
- CopyCtorBase(const CopyCtorBase&) = default;
- CopyCtorBase(CopyCtorBase&&) = default;
- CopyCtorBase& operator=(const CopyCtorBase&) = default;
- CopyCtorBase& operator=(CopyCtorBase&&) = default;
-};
-
-template <typename T>
-struct CopyCtorBase<T, false> {
- CopyCtorBase() = default;
- CopyCtorBase(const CopyCtorBase&) = delete;
- CopyCtorBase(CopyCtorBase&&) = default;
- CopyCtorBase& operator=(const CopyCtorBase&) = default;
- CopyCtorBase& operator=(CopyCtorBase&&) = default;
-};
-
-template <typename T, bool = std::is_move_constructible<T>::value>
-struct MoveCtorBase {
- MoveCtorBase() = default;
- MoveCtorBase(const MoveCtorBase&) = default;
- MoveCtorBase(MoveCtorBase&&) = default;
- MoveCtorBase& operator=(const MoveCtorBase&) = default;
- MoveCtorBase& operator=(MoveCtorBase&&) = default;
-};
-
-template <typename T>
-struct MoveCtorBase<T, false> {
- MoveCtorBase() = default;
- MoveCtorBase(const MoveCtorBase&) = default;
- MoveCtorBase(MoveCtorBase&&) = delete;
- MoveCtorBase& operator=(const MoveCtorBase&) = default;
- MoveCtorBase& operator=(MoveCtorBase&&) = default;
-};
-
-template <typename T, bool = std::is_copy_constructible<T>::value&&
- std::is_copy_assignable<T>::value>
-struct CopyAssignBase {
- CopyAssignBase() = default;
- CopyAssignBase(const CopyAssignBase&) = default;
- CopyAssignBase(CopyAssignBase&&) = default;
- CopyAssignBase& operator=(const CopyAssignBase&) = default;
- CopyAssignBase& operator=(CopyAssignBase&&) = default;
-};
-
-template <typename T>
-struct CopyAssignBase<T, false> {
- CopyAssignBase() = default;
- CopyAssignBase(const CopyAssignBase&) = default;
- CopyAssignBase(CopyAssignBase&&) = default;
- CopyAssignBase& operator=(const CopyAssignBase&) = delete;
- CopyAssignBase& operator=(CopyAssignBase&&) = default;
-};
-
-template <typename T, bool = std::is_move_constructible<T>::value&&
- std::is_move_assignable<T>::value>
-struct MoveAssignBase {
- MoveAssignBase() = default;
- MoveAssignBase(const MoveAssignBase&) = default;
- MoveAssignBase(MoveAssignBase&&) = default;
- MoveAssignBase& operator=(const MoveAssignBase&) = default;
- MoveAssignBase& operator=(MoveAssignBase&&) = default;
-};
-
-template <typename T>
-struct MoveAssignBase<T, false> {
- MoveAssignBase() = default;
- MoveAssignBase(const MoveAssignBase&) = default;
- MoveAssignBase(MoveAssignBase&&) = default;
- MoveAssignBase& operator=(const MoveAssignBase&) = default;
- MoveAssignBase& operator=(MoveAssignBase&&) = delete;
-};
-
-ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
-
-} // namespace internal_statusor
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
diff --git a/third_party/abseil-cpp/absl/status/status.cc b/third_party/abseil-cpp/absl/status/status.cc
index bcf3413e5f..df3b740f77 100644
--- a/third_party/abseil-cpp/absl/status/status.cc
+++ b/third_party/abseil-cpp/absl/status/status.cc
@@ -27,6 +27,8 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
+// The implementation was intentionally kept same as util::error::Code_Name()
+// to ease the migration.
std::string StatusCodeToString(StatusCode code) {
switch (code) {
case StatusCode::kOk:
@@ -78,7 +80,7 @@ static int FindPayloadIndexByUrl(const Payloads* payloads,
absl::string_view type_url) {
if (payloads == nullptr) return -1;
- for (size_t i = 0; i < payloads->size(); ++i) {
+ for (int i = 0; i < payloads->size(); ++i) {
if ((*payloads)[i].type_url == type_url) return i;
}
@@ -161,21 +163,21 @@ bool Status::ErasePayload(absl::string_view type_url) {
}
void Status::ForEachPayload(
- absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
+ const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
const {
if (auto* payloads = GetPayloads()) {
bool in_reverse =
payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
- for (size_t index = 0; index < payloads->size(); ++index) {
+ for (int index = 0; index < payloads->size(); ++index) {
const auto& elem =
(*payloads)[in_reverse ? payloads->size() - 1 - index : index];
#ifdef NDEBUG
visitor(elem.type_url, elem.payload);
#else
- // In debug mode invalidate the type url to prevent users from relying on
- // this string lifetime.
+ // In debug mode invaldiate the type url to prevent users from relying on
+ // this std::string lifetime.
// NOLINTNEXTLINE intentional extra conversion to force temporary.
visitor(std::string(elem.type_url), elem.payload);
@@ -207,10 +209,20 @@ void Status::UnrefNonInlined(uintptr_t rep) {
}
}
+uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg,
+ std::unique_ptr<status_internal::Payloads> payloads) {
+ status_internal::StatusRep* rep = new status_internal::StatusRep;
+ rep->ref.store(1, std::memory_order_relaxed);
+ rep->code = code;
+ rep->message.assign(msg.data(), msg.size());
+ rep->payloads = std::move(payloads);
+ return PointerToRep(rep);
+}
+
Status::Status(absl::StatusCode code, absl::string_view msg)
: rep_(CodeToInlinedRep(code)) {
if (code != absl::StatusCode::kOk && !msg.empty()) {
- rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
+ rep_ = NewRep(code, msg, nullptr);
}
}
@@ -229,9 +241,8 @@ absl::StatusCode Status::code() const {
void Status::PrepareToModify() {
ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
if (IsInlined(rep_)) {
- rep_ = PointerToRep(new status_internal::StatusRep(
- static_cast<absl::StatusCode>(raw_code()), absl::string_view(),
- nullptr));
+ rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()),
+ absl::string_view(), nullptr);
return;
}
@@ -242,9 +253,7 @@ void Status::PrepareToModify() {
if (rep->payloads) {
payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
}
- status_internal::StatusRep* const new_rep = new status_internal::StatusRep(
- rep->code, message(), std::move(payloads));
- rep_ = PointerToRep(new_rep);
+ rep_ = NewRep(rep->code, message(), std::move(payloads));
UnrefNonInlined(rep_i);
}
}
@@ -283,32 +292,26 @@ bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
return true;
}
-std::string Status::ToStringSlow(StatusToStringMode mode) const {
+std::string Status::ToStringSlow() const {
std::string text;
absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
-
- const bool with_payload = (mode & StatusToStringMode::kWithPayload) ==
- StatusToStringMode::kWithPayload;
-
- if (with_payload) {
- status_internal::StatusPayloadPrinter printer =
- status_internal::GetStatusPayloadPrinter();
- this->ForEachPayload([&](absl::string_view type_url,
- const absl::Cord& payload) {
- absl::optional<std::string> result;
- if (printer) result = printer(type_url, payload);
- absl::StrAppend(
- &text, " [", type_url, "='",
- result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
- "']");
- });
- }
+ status_internal::StatusPayloadPrinter printer =
+ status_internal::GetStatusPayloadPrinter();
+ this->ForEachPayload([&](absl::string_view type_url,
+ const absl::Cord& payload) {
+ absl::optional<std::string> result;
+ if (printer) result = printer(type_url, payload);
+ absl::StrAppend(
+ &text, " [", type_url, "='",
+ result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
+ "']");
+ });
return text;
}
std::ostream& operator<<(std::ostream& os, const Status& x) {
- os << x.ToString(StatusToStringMode::kWithEverything);
+ os << x.ToString();
return os;
}
diff --git a/third_party/abseil-cpp/absl/status/status.h b/third_party/abseil-cpp/absl/status/status.h
index 39071e5f4a..9706d4bace 100644
--- a/third_party/abseil-cpp/absl/status/status.h
+++ b/third_party/abseil-cpp/absl/status/status.h
@@ -11,43 +11,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: status.h
-// -----------------------------------------------------------------------------
-//
-// This header file defines the Abseil `status` library, consisting of:
-//
-// * An `absl::Status` class for holding error handling information
-// * A set of canonical `absl::StatusCode` error codes, and associated
-// utilities for generating and propagating status codes.
-// * A set of helper functions for creating status codes and checking their
-// values
-//
-// Within Google, `absl::Status` is the primary mechanism for gracefully
-// handling errors across API boundaries (and in particular across RPC
-// boundaries). Some of these errors may be recoverable, but others may not.
-// Most functions that can produce a recoverable error should be designed to
-// return an `absl::Status` (or `absl::StatusOr`).
-//
-// Example:
-//
-// absl::Status myFunction(absl::string_view fname, ...) {
-// ...
-// // encounter error
-// if (error condition) {
-// return absl::InvalidArgumentError("bad mode");
-// }
-// // else, return OK
-// return absl::OkStatus();
-// }
-//
-// An `absl::Status` is designed to either return "OK" or one of a number of
-// different error codes, corresponding to typical error conditions.
-// In almost all cases, when using `absl::Status` you should use the canonical
-// error codes (of type `absl::StatusCode`) enumerated in this header file.
-// These canonical codes are understood across the codebase and will be
-// accepted across all API and RPC boundaries.
#ifndef ABSL_STATUS_STATUS_H_
#define ABSL_STATUS_STATUS_H_
@@ -55,543 +18,168 @@
#include <string>
#include "absl/container/inlined_vector.h"
-#include "absl/functional/function_ref.h"
-#include "absl/status/internal/status_internal.h"
#include "absl/strings/cord.h"
-#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-// absl::StatusCode
-//
-// An `absl::StatusCode` is an enumerated type indicating either no error ("OK")
-// or an error condition. In most cases, an `absl::Status` indicates a
-// recoverable error, and the purpose of signalling an error is to indicate what
-// action to take in response to that error. These error codes map to the proto
-// RPC error codes indicated in https://cloud.google.com/apis/design/errors.
-//
-// The errors listed below are the canonical errors associated with
-// `absl::Status` and are used throughout the codebase. As a result, these
-// error codes are somewhat generic.
-//
-// In general, try to return the most specific error that applies if more than
-// one error may pertain. For example, prefer `kOutOfRange` over
-// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
-// `kAlreadyExists` over `kFailedPrecondition`.
-//
-// Because these errors may cross RPC boundaries, these codes are tied to the
-// `google.rpc.Code` definitions within
-// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
-// The string value of these RPC codes is denoted within each enum below.
-//
-// If your error handling code requires more context, you can attach payloads
-// to your status. See `absl::Status::SetPayload()` and
-// `absl::Status::GetPayload()` below.
enum class StatusCode : int {
- // StatusCode::kOk
- //
- // kOK (gRPC code "OK") does not indicate an error; this value is returned on
- // success. It is typical to check for this value before proceeding on any
- // given call across an API or RPC boundary. To check this value, use the
- // `absl::Status::ok()` member function rather than inspecting the raw code.
kOk = 0,
-
- // StatusCode::kCancelled
- //
- // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
- // typically by the caller.
kCancelled = 1,
-
- // StatusCode::kUnknown
- //
- // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In
- // general, more specific errors should be raised, if possible. Errors raised
- // by APIs that do not return enough error information may be converted to
- // this error.
kUnknown = 2,
-
- // StatusCode::kInvalidArgument
- //
- // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
- // specified an invalid argument, such as a malformed filename. Note that use
- // of such errors should be narrowly limited to indicate the invalid nature of
- // the arguments themselves. Errors with validly formed arguments that may
- // cause errors with the state of the receiving system should be denoted with
- // `kFailedPrecondition` instead.
kInvalidArgument = 3,
-
- // StatusCode::kDeadlineExceeded
- //
- // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline
- // expired before the operation could complete. For operations that may change
- // state within a system, this error may be returned even if the operation has
- // completed successfully. For example, a successful response from a server
- // could have been delayed long enough for the deadline to expire.
kDeadlineExceeded = 4,
-
- // StatusCode::kNotFound
- //
- // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as
- // a file or directory) was not found.
- //
- // `kNotFound` is useful if a request should be denied for an entire class of
- // users, such as during a gradual feature rollout or undocumented allow list.
- // If a request should be denied for specific sets of users, such as through
- // user-based access control, use `kPermissionDenied` instead.
kNotFound = 5,
-
- // StatusCode::kAlreadyExists
- //
- // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates that the entity a
- // caller attempted to create (such as a file or directory) is already
- // present.
kAlreadyExists = 6,
-
- // StatusCode::kPermissionDenied
- //
- // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller
- // does not have permission to execute the specified operation. Note that this
- // error is different than an error due to an *un*authenticated user. This
- // error code does not imply the request is valid or the requested entity
- // exists or satisfies any other pre-conditions.
- //
- // `kPermissionDenied` must not be used for rejections caused by exhausting
- // some resource. Instead, use `kResourceExhausted` for those errors.
- // `kPermissionDenied` must not be used if the caller cannot be identified.
- // Instead, use `kUnauthenticated` for those errors.
kPermissionDenied = 7,
-
- // StatusCode::kResourceExhausted
- //
- // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource
- // has been exhausted, perhaps a per-user quota, or perhaps the entire file
- // system is out of space.
kResourceExhausted = 8,
-
- // StatusCode::kFailedPrecondition
- //
- // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the
- // operation was rejected because the system is not in a state required for
- // the operation's execution. For example, a directory to be deleted may be
- // non-empty, an "rmdir" operation is applied to a non-directory, etc.
- //
- // Some guidelines that may help a service implementer in deciding between
- // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
- //
- // (a) Use `kUnavailable` if the client can retry just the failing call.
- // (b) Use `kAborted` if the client should retry at a higher transaction
- // level (such as when a client-specified test-and-set fails, indicating
- // the client should restart a read-modify-write sequence).
- // (c) Use `kFailedPrecondition` if the client should not retry until
- // the system state has been explicitly fixed. For example, if a "rmdir"
- // fails because the directory is non-empty, `kFailedPrecondition`
- // should be returned since the client should not retry unless
- // the files are deleted from the directory.
kFailedPrecondition = 9,
-
- // StatusCode::kAborted
- //
- // kAborted (gRPC code "ABORTED") indicates the operation was aborted,
- // typically due to a concurrency issue such as a sequencer check failure or a
- // failed transaction.
- //
- // See the guidelines above for deciding between `kFailedPrecondition`,
- // `kAborted`, and `kUnavailable`.
kAborted = 10,
-
- // StatusCode::kOutOfRange
- //
- // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
- // attempted past the valid range, such as seeking or reading past an
- // end-of-file.
- //
- // Unlike `kInvalidArgument`, this error indicates a problem that may
- // be fixed if the system state changes. For example, a 32-bit file
- // system will generate `kInvalidArgument` if asked to read at an
- // offset that is not in the range [0,2^32-1], but it will generate
- // `kOutOfRange` if asked to read from an offset past the current
- // file size.
- //
- // There is a fair bit of overlap between `kFailedPrecondition` and
- // `kOutOfRange`. We recommend using `kOutOfRange` (the more specific
- // error) when it applies so that callers who are iterating through
- // a space can easily look for an `kOutOfRange` error to detect when
- // they are done.
kOutOfRange = 11,
-
- // StatusCode::kUnimplemented
- //
- // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not
- // implemented or supported in this service. In this case, the operation
- // should not be re-attempted.
kUnimplemented = 12,
-
- // StatusCode::kInternal
- //
- // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred
- // and some invariants expected by the underlying system have not been
- // satisfied. This error code is reserved for serious errors.
kInternal = 13,
-
- // StatusCode::kUnavailable
- //
- // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently
- // unavailable and that this is most likely a transient condition. An error
- // such as this can be corrected by retrying with a backoff scheme. Note that
- // it is not always safe to retry non-idempotent operations.
- //
- // See the guidelines above for deciding between `kFailedPrecondition`,
- // `kAborted`, and `kUnavailable`.
kUnavailable = 14,
-
- // StatusCode::kDataLoss
- //
- // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or
- // corruption has occurred. As this error is serious, proper alerting should
- // be attached to errors such as this.
kDataLoss = 15,
-
- // StatusCode::kUnauthenticated
- //
- // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request
- // does not have valid authentication credentials for the operation. Correct
- // the authentication and try again.
kUnauthenticated = 16,
-
- // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_
- //
- // NOTE: this error code entry should not be used and you should not rely on
- // its value, which may change.
- //
- // The purpose of this enumerated value is to force people who handle status
- // codes with `switch()` statements to *not* simply enumerate all possible
- // values, but instead provide a "default:" case. Providing such a default
- // case ensures that code will compile when new codes are added.
kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
};
-// StatusCodeToString()
-//
// Returns the name for the status code, or "" if it is an unknown value.
std::string StatusCodeToString(StatusCode code);
-// operator<<
-//
// Streams StatusCodeToString(code) to `os`.
std::ostream& operator<<(std::ostream& os, StatusCode code);
-// absl::StatusToStringMode
-//
-// An `absl::StatusToStringMode` is an enumerated type indicating how
-// `absl::Status::ToString()` should construct the output string for a non-ok
-// status.
-enum class StatusToStringMode : int {
- // ToString will not contain any extra data (such as payloads). It will only
- // contain the error code and message, if any.
- kWithNoExtraData = 0,
- // ToString will contain the payloads.
- kWithPayload = 1 << 0,
- // ToString will include all the extra data this Status has.
- kWithEverything = ~kWithNoExtraData,
- // Default mode used by ToString. Its exact value might change in the future.
- kDefault = kWithPayload,
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+ std::string type_url;
+ absl::Cord payload;
};
-// absl::StatusToStringMode is specified as a bitmask type, which means the
-// following operations must be provided:
-inline constexpr StatusToStringMode operator&(StatusToStringMode lhs,
- StatusToStringMode rhs) {
- return static_cast<StatusToStringMode>(static_cast<int>(lhs) &
- static_cast<int>(rhs));
-}
-inline constexpr StatusToStringMode operator|(StatusToStringMode lhs,
- StatusToStringMode rhs) {
- return static_cast<StatusToStringMode>(static_cast<int>(lhs) |
- static_cast<int>(rhs));
-}
-inline constexpr StatusToStringMode operator^(StatusToStringMode lhs,
- StatusToStringMode rhs) {
- return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^
- static_cast<int>(rhs));
-}
-inline constexpr StatusToStringMode operator~(StatusToStringMode arg) {
- return static_cast<StatusToStringMode>(~static_cast<int>(arg));
-}
-inline StatusToStringMode& operator&=(StatusToStringMode& lhs,
- StatusToStringMode rhs) {
- lhs = lhs & rhs;
- return lhs;
-}
-inline StatusToStringMode& operator|=(StatusToStringMode& lhs,
- StatusToStringMode rhs) {
- lhs = lhs | rhs;
- return lhs;
-}
-inline StatusToStringMode& operator^=(StatusToStringMode& lhs,
- StatusToStringMode rhs) {
- lhs = lhs ^ rhs;
- return lhs;
-}
+using Payloads = absl::InlinedVector<Payload, 1>;
-// absl::Status
-//
-// The `absl::Status` class is generally used to gracefully handle errors
-// across API boundaries (and in particular across RPC boundaries). Some of
-// these errors may be recoverable, but others may not. Most
-// functions which can produce a recoverable error should be designed to return
-// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds
-// either an object of type `T` or an error).
-//
-// API developers should construct their functions to return `absl::OkStatus()`
-// upon success, or an `absl::StatusCode` upon another type of error (e.g
-// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
-// functions to construct each status code.
-//
-// Example:
-//
-// absl::Status myFunction(absl::string_view fname, ...) {
-// ...
-// // encounter error
-// if (error condition) {
-// // Construct an absl::StatusCode::kInvalidArgument error
-// return absl::InvalidArgumentError("bad mode");
-// }
-// // else, return OK
-// return absl::OkStatus();
-// }
-//
-// Users handling status error codes should prefer checking for an OK status
-// using the `ok()` member function. Handling multiple error codes may justify
-// use of switch statement, but only check for error codes you know how to
-// handle; do not try to exhaustively match against all canonical error codes.
-// Errors that cannot be handled should be logged and/or propagated for higher
-// levels to deal with. If you do use a switch statement, make sure that you
-// also provide a `default:` switch case, so that code does not break as other
-// canonical codes are added to the API.
-//
-// Example:
-//
-// absl::Status result = DoSomething();
-// if (!result.ok()) {
-// LOG(ERROR) << result;
-// }
-//
-// // Provide a default if switching on multiple error codes
-// switch (result.code()) {
-// // The user hasn't authenticated. Ask them to reauth
-// case absl::StatusCode::kUnauthenticated:
-// DoReAuth();
-// break;
-// // The user does not have permission. Log an error.
-// case absl::StatusCode::kPermissionDenied:
-// LOG(ERROR) << result;
-// break;
-// // Propagate the error otherwise.
-// default:
-// return true;
-// }
-//
-// An `absl::Status` can optionally include a payload with more information
-// about the error. Typically, this payload serves one of several purposes:
-//
-// * It may provide more fine-grained semantic information about the error to
-// facilitate actionable remedies.
-// * It may provide human-readable contexual information that is more
-// appropriate to display to an end user.
-//
-// Example:
-//
-// absl::Status result = DoSomething();
-// // Inform user to retry after 30 seconds
-// // See more error details in googleapis/google/rpc/error_details.proto
-// if (absl::IsResourceExhausted(result)) {
-// google::rpc::RetryInfo info;
-// info.retry_delay().seconds() = 30;
-// // Payloads require a unique key (a URL to ensure no collisions with
-// // other payloads), and an `absl::Cord` to hold the encoded data.
-// absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo";
-// result.SetPayload(url, info.SerializeAsCord());
-// return result;
-// }
-//
-// For documentation see https://abseil.io/docs/cpp/guides/status.
-//
-// Returned Status objects may not be ignored. status_internal.h has a forward
-// declaration of the form
-// class ABSL_MUST_USE_RESULT Status;
-class Status final {
- public:
- // Constructors
+// Reference-counted representation of Status data.
+struct StatusRep {
+ std::atomic<int32_t> ref;
+ absl::StatusCode code;
+ std::string message;
+ std::unique_ptr<status_internal::Payloads> payloads;
+};
+
+absl::StatusCode MapToLocalCode(int value);
+} // namespace status_internal
- // This default constructor creates an OK status with no message or payload.
- // Avoid this constructor and prefer explicit construction of an OK status
- // with `absl::OkStatus()`.
+class ABSL_MUST_USE_RESULT Status final {
+ public:
+ // Creates an OK status with no message or payload.
Status();
- // Creates a status in the canonical error space with the specified
- // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT
- // `msg` is ignored and an object identical to an OK status is constructed.
+ // Create a status in the canonical error space with the specified code and
+ // error message. If `code == util::error::OK`, `msg` is ignored and an
+ // object identical to an OK status is constructed.
//
- // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT
+ // `msg` must be in UTF-8. The implementation may complain (e.g.,
// by printing a warning) if it is not.
Status(absl::StatusCode code, absl::string_view msg);
Status(const Status&);
Status& operator=(const Status& x);
- // Move operators
-
+ // Move operations.
// The moved-from state is valid but unspecified.
Status(Status&&) noexcept;
Status& operator=(Status&&);
~Status();
- // Status::Update()
- //
- // Updates the existing status with `new_status` provided that `this->ok()`.
- // If the existing status already contains a non-OK error, this update has no
- // effect and preserves the current data. Note that this behavior may change
- // in the future to augment a current non-ok status with additional
- // information about `new_status`.
+ // If `this->ok()`, stores `new_status` into *this. If `!this->ok()`,
+ // preserves the current data. May, in the future, augment the current status
+ // with additional information about `new_status`.
//
- // `Update()` provides a convenient way of keeping track of the first error
- // encountered.
- //
- // Example:
- // // Instead of "if (overall_status.ok()) overall_status = new_status"
+ // Convenient way of keeping track of the first error encountered.
+ // Instead of:
+ // if (overall_status.ok()) overall_status = new_status
+ // Use:
// overall_status.Update(new_status);
//
+ // Style guide exception for rvalue reference granted in CL 153567220.
void Update(const Status& new_status);
void Update(Status&& new_status);
- // Status::ok()
- //
- // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
- // member function.
+ // Returns true if the Status is OK.
ABSL_MUST_USE_RESULT bool ok() const;
- // Status::code()
- //
- // Returns the canonical error code of type `absl::StatusCode` of this status.
+ // Returns the (canonical) error code.
absl::StatusCode code() const;
- // Status::raw_code()
- //
- // Returns a raw (canonical) error code corresponding to the enum value of
- // `google.rpc.Code` definitions within
- // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.
- // These values could be out of the range of canonical `absl::StatusCode`
- // enum values.
- //
- // NOTE: This function should only be called when converting to an associated
- // wire format. Use `Status::code()` for error handling.
+ // Returns the raw (canonical) error code which could be out of the range of
+ // the local `absl::StatusCode` enum. NOTE: This should only be called when
+ // converting to wire format. Use `code` for error handling.
int raw_code() const;
- // Status::message()
- //
- // Returns the error message associated with this error code, if available.
- // Note that this message rarely describes the error code. It is not unusual
- // for the error message to be the empty string. As a result, prefer
- // `operator<<` or `Status::ToString()` for debug logging.
+ // Returns the error message. Note: prefer ToString() for debug logging.
+ // This message rarely describes the error code. It is not unusual for the
+ // error message to be the empty std::string.
absl::string_view message() const;
friend bool operator==(const Status&, const Status&);
friend bool operator!=(const Status&, const Status&);
- // Status::ToString()
- //
- // Returns a string based on the `mode`. By default, it returns combination of
- // the error code name, the message and any associated payload messages. This
- // string is designed simply to be human readable and its exact format should
- // not be load bearing. Do not depend on the exact format of the result of
- // `ToString()` which is subject to change.
- //
- // The printed code name and the message are generally substrings of the
- // result, and the payloads to be printed use the status payload printer
- // mechanism (which is internal).
- std::string ToString(
- StatusToStringMode mode = StatusToStringMode::kDefault) const;
+ // Returns a combination of the error code name, the message and the payloads.
+ // You can expect the code name and the message to be substrings of the
+ // result, and the payloads to be printed by the registered printer extensions
+ // if they are recognized.
+ // WARNING: Do not depend on the exact format of the result of `ToString()`
+ // which is subject to change.
+ std::string ToString() const;
- // Status::IgnoreError()
- //
// Ignores any errors. This method does nothing except potentially suppress
// complaints from any tools that are checking that errors are not dropped on
// the floor.
void IgnoreError() const;
- // swap()
- //
- // Swap the contents of one status with another.
+ // Swap the contents of `a` with `b`
friend void swap(Status& a, Status& b);
- //----------------------------------------------------------------------------
- // Payload Management APIs
- //----------------------------------------------------------------------------
-
- // A payload may be attached to a status to provide additional context to an
- // error that may not be satisifed by an existing `absl::StatusCode`.
- // Typically, this payload serves one of several purposes:
- //
- // * It may provide more fine-grained semantic information about the error
- // to facilitate actionable remedies.
- // * It may provide human-readable contexual information that is more
- // appropriate to display to an end user.
- //
- // A payload consists of a [key,value] pair, where the key is a string
- // referring to a unique "type URL" and the value is an object of type
- // `absl::Cord` to hold the contextual data.
- //
- // The "type URL" should be unique and follow the format of a URL
- // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some
- // documentation or schema on how to interpret its associated data. For
- // example, the default type URL for a protobuf message type is
- // "type.googleapis.com/packagename.messagename". Other custom wire formats
- // should define the format of type URL in a similar practice so as to
- // minimize the chance of conflict between type URLs.
- // Users should ensure that the type URL can be mapped to a concrete
+ // Payload management APIs
+
+ // Type URL should be unique and follow the naming convention below:
+ // The idea of type URL comes from `google.protobuf.Any`
+ // (https://developers.google.com/protocol-buffers/docs/proto3#any). The
+ // type URL should be globally unique and follow the format of URL
+ // (https://en.wikipedia.org/wiki/URL). The default type URL for a given
+ // protobuf message type is "type.googleapis.com/packagename.messagename". For
+ // other custom wire formats, users should define the format of type URL in a
+ // similar practice so as to minimize the chance of conflict between type
+ // URLs. Users should make sure that the type URL can be mapped to a concrete
// C++ type if they want to deserialize the payload and read it effectively.
- //
- // To attach a payload to a status object, call `Status::SetPayload()`,
- // passing it the type URL and an `absl::Cord` of associated data. Similarly,
- // to extract the payload from a status, call `Status::GetPayload()`. You
- // may attach multiple payloads (with differing type URLs) to any given
- // status object, provided that the status is currently exhibiting an error
- // code (i.e. is not OK).
-
- // Status::GetPayload()
- //
- // Gets the payload of a status given its unique `type_url` key, if present.
+
+ // Gets the payload based for `type_url` key, if it is present.
absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
- // Status::SetPayload()
+ // Sets the payload for `type_url` key for a non-ok status, overwriting any
+ // existing payload for `type_url`.
//
- // Sets the payload for a non-ok status using a `type_url` key, overwriting
- // any existing payload for that `type_url`.
- //
- // NOTE: This function does nothing if the Status is ok.
+ // NOTE: Does nothing if the Status is ok.
void SetPayload(absl::string_view type_url, absl::Cord payload);
- // Status::ErasePayload()
- //
- // Erases the payload corresponding to the `type_url` key. Returns `true` if
+ // Erases the payload corresponding to the `type_url` key. Returns true if
// the payload was present.
bool ErasePayload(absl::string_view type_url);
- // Status::ForEachPayload()
- //
- // Iterates over the stored payloads and calls the
- // `visitor(type_key, payload)` callable for each one.
+ // Iterates over the stored payloads and calls `visitor(type_key, payload)`
+ // for each one.
//
- // NOTE: The order of calls to `visitor()` is not specified and may change at
+ // NOTE: The order of calls to `visitor` is not specified and may change at
// any time.
//
- // NOTE: Any mutation on the same 'absl::Status' object during visitation is
+ // NOTE: Any mutation on the same 'Status' object during visitation is
// forbidden and could result in undefined behavior.
void ForEachPayload(
- absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
+ const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
const;
private:
@@ -613,9 +201,8 @@ class Status final {
status_internal::Payloads* GetPayloads();
// Takes ownership of payload.
- static uintptr_t NewRep(
- absl::StatusCode code, absl::string_view msg,
- std::unique_ptr<status_internal::Payloads> payload);
+ static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg,
+ std::unique_ptr<status_internal::Payloads> payload);
static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
// MSVC 14.0 limitation requires the const.
@@ -644,7 +231,8 @@ class Status final {
static uintptr_t PointerToRep(status_internal::StatusRep* r);
static status_internal::StatusRep* RepToPointer(uintptr_t r);
- std::string ToStringSlow(StatusToStringMode mode) const;
+ // Returns std::string for non-ok Status.
+ std::string ToStringSlow() const;
// Status supports two different representations.
// - When the low bit is off it is an inlined representation.
@@ -657,93 +245,14 @@ class Status final {
uintptr_t rep_;
};
-// OkStatus()
-//
-// Returns an OK status, equivalent to a default constructed instance. Prefer
-// usage of `absl::OkStatus()` when constructing such an OK status.
+// Returns an OK status, equivalent to a default constructed instance.
Status OkStatus();
-// operator<<()
-//
// Prints a human-readable representation of `x` to `os`.
std::ostream& operator<<(std::ostream& os, const Status& x);
-// IsAborted()
-// IsAlreadyExists()
-// IsCancelled()
-// IsDataLoss()
-// IsDeadlineExceeded()
-// IsFailedPrecondition()
-// IsInternal()
-// IsInvalidArgument()
-// IsNotFound()
-// IsOutOfRange()
-// IsPermissionDenied()
-// IsResourceExhausted()
-// IsUnauthenticated()
-// IsUnavailable()
-// IsUnimplemented()
-// IsUnknown()
-//
-// These convenience functions return `true` if a given status matches the
-// `absl::StatusCode` error code of its associated function.
-ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
-ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
-ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
-ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
-ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
-ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
-ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
-
-// AbortedError()
-// AlreadyExistsError()
-// CancelledError()
-// DataLossError()
-// DeadlineExceededError()
-// FailedPreconditionError()
-// InternalError()
-// InvalidArgumentError()
-// NotFoundError()
-// OutOfRangeError()
-// PermissionDeniedError()
-// ResourceExhaustedError()
-// UnauthenticatedError()
-// UnavailableError()
-// UnimplementedError()
-// UnknownError()
-//
-// These convenience functions create an `absl::Status` object with an error
-// code as indicated by the associated function name, using the error message
-// passed in `message`.
-Status AbortedError(absl::string_view message);
-Status AlreadyExistsError(absl::string_view message);
-Status CancelledError(absl::string_view message);
-Status DataLossError(absl::string_view message);
-Status DeadlineExceededError(absl::string_view message);
-Status FailedPreconditionError(absl::string_view message);
-Status InternalError(absl::string_view message);
-Status InvalidArgumentError(absl::string_view message);
-Status NotFoundError(absl::string_view message);
-Status OutOfRangeError(absl::string_view message);
-Status PermissionDeniedError(absl::string_view message);
-Status ResourceExhaustedError(absl::string_view message);
-Status UnauthenticatedError(absl::string_view message);
-Status UnavailableError(absl::string_view message);
-Status UnimplementedError(absl::string_view message);
-Status UnknownError(absl::string_view message);
-
-//------------------------------------------------------------------------------
+// -----------------------------------------------------------------
// Implementation details follow
-//------------------------------------------------------------------------------
inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
@@ -767,11 +276,9 @@ inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
inline Status& Status::operator=(Status&& x) {
uintptr_t old_rep = rep_;
- if (x.rep_ != old_rep) {
- rep_ = x.rep_;
- x.rep_ = MovedFromRep();
- Unref(old_rep);
- }
+ rep_ = x.rep_;
+ x.rep_ = MovedFromRep();
+ Unref(old_rep);
return *this;
}
@@ -808,8 +315,8 @@ inline bool operator!=(const Status& lhs, const Status& rhs) {
return !(lhs == rhs);
}
-inline std::string Status::ToString(StatusToStringMode mode) const {
- return ok() ? "OK" : ToStringSlow(mode);
+inline std::string Status::ToString() const {
+ return ok() ? "OK" : ToStringSlow();
}
inline void Status::IgnoreError() const {
@@ -871,11 +378,50 @@ inline void Status::Unref(uintptr_t rep) {
inline Status OkStatus() { return Status(); }
+// Each of the functions below creates a Status object with a particular error
+// code and the given message. The error code of the returned status object
+// matches the name of the function.
+Status AbortedError(absl::string_view message);
+Status AlreadyExistsError(absl::string_view message);
+Status CancelledError(absl::string_view message);
+Status DataLossError(absl::string_view message);
+Status DeadlineExceededError(absl::string_view message);
+Status FailedPreconditionError(absl::string_view message);
+Status InternalError(absl::string_view message);
+Status InvalidArgumentError(absl::string_view message);
+Status NotFoundError(absl::string_view message);
+Status OutOfRangeError(absl::string_view message);
+Status PermissionDeniedError(absl::string_view message);
+Status ResourceExhaustedError(absl::string_view message);
+Status UnauthenticatedError(absl::string_view message);
+Status UnavailableError(absl::string_view message);
+Status UnimplementedError(absl::string_view message);
+Status UnknownError(absl::string_view message);
+
// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
// and an empty message. It is provided only for efficiency, given that
// message-less kCancelled errors are common in the infrastructure.
inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
+// Each of the functions below returns true if the given status matches the
+// error code implied by the function's name.
+ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
+ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
+ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
+ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
+ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
+ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
+ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/status/status_payload_printer.cc b/third_party/abseil-cpp/absl/status/status_payload_printer.cc
index a47aea11c2..ad96d76acf 100644
--- a/third_party/abseil-cpp/absl/status/status_payload_printer.cc
+++ b/third_party/abseil-cpp/absl/status/status_payload_printer.cc
@@ -16,21 +16,26 @@
#include <atomic>
#include "absl/base/attributes.h"
-#include "absl/base/internal/atomic_hook.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace status_internal {
-ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
-static absl::base_internal::AtomicHook<StatusPayloadPrinter> storage;
+namespace {
+// Tried constant initialized global variable but it doesn't work with Lexan
+// (MSVC's `std::atomic` has trouble constant initializing).
+std::atomic<StatusPayloadPrinter>& GetStatusPayloadPrinterStorage() {
+ ABSL_CONST_INIT static std::atomic<StatusPayloadPrinter> instance{nullptr};
+ return instance;
+}
+} // namespace
void SetStatusPayloadPrinter(StatusPayloadPrinter printer) {
- storage.Store(printer);
+ GetStatusPayloadPrinterStorage().store(printer, std::memory_order_relaxed);
}
StatusPayloadPrinter GetStatusPayloadPrinter() {
- return storage.Load();
+ return GetStatusPayloadPrinterStorage().load(std::memory_order_relaxed);
}
} // namespace status_internal
diff --git a/third_party/abseil-cpp/absl/status/status_test.cc b/third_party/abseil-cpp/absl/status/status_test.cc
index 1b038f6d98..ca9488ad22 100644
--- a/third_party/abseil-cpp/absl/status/status_test.cc
+++ b/third_party/abseil-cpp/absl/status/status_test.cc
@@ -36,9 +36,7 @@ TEST(StatusCode, InsertionOperator) {
// its creator, and its classifier.
struct ErrorTest {
absl::StatusCode code;
- using Creator = absl::Status (*)(
- absl::string_view
- );
+ using Creator = absl::Status (*)(absl::string_view);
using Classifier = bool (*)(const absl::Status&);
Creator creator;
Classifier classifier;
@@ -80,9 +78,7 @@ TEST(Status, CreateAndClassify) {
// expected error code and message.
std::string message =
absl::StrCat("error code ", test.code, " test message");
- absl::Status status = test.creator(
- message
- );
+ absl::Status status = test.creator(message);
EXPECT_EQ(test.code, status.code());
EXPECT_EQ(message, status.message());
@@ -284,27 +280,6 @@ TEST(Status, ToString) {
HasSubstr("[bar='\\xff']")));
}
-TEST(Status, ToStringMode) {
- absl::Status s(absl::StatusCode::kInternal, "fail");
- s.SetPayload("foo", absl::Cord("bar"));
- s.SetPayload("bar", absl::Cord("\377"));
-
- EXPECT_EQ("INTERNAL: fail",
- s.ToString(absl::StatusToStringMode::kWithNoExtraData));
-
- EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),
- AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
- HasSubstr("[bar='\\xff']")));
-
- EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
- AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
- HasSubstr("[bar='\\xff']")));
-
- EXPECT_THAT(s.ToString(~absl::StatusToStringMode::kWithPayload),
- AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
- Not(HasSubstr("[bar='\\xff']"))));
-}
-
absl::Status EraseAndReturn(const absl::Status& base) {
absl::Status copy = base;
EXPECT_TRUE(copy.ErasePayload(kUrl1));
@@ -422,12 +397,6 @@ TEST(Status, MoveAssignment) {
assignee = std::move(status);
EXPECT_EQ(assignee, copy);
}
- {
- absl::Status status(absl::StatusCode::kInvalidArgument, "message");
- absl::Status copy(status);
- status = static_cast<absl::Status&&>(status);
- EXPECT_EQ(status, copy);
- }
}
TEST(Status, Update) {
@@ -485,4 +454,5 @@ TEST(Status, Swap) {
test_swap(no_payload, with_payload);
test_swap(with_payload, no_payload);
}
+
} // namespace
diff --git a/third_party/abseil-cpp/absl/status/statusor.cc b/third_party/abseil-cpp/absl/status/statusor.cc
deleted file mode 100644
index 96642b340f..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2020 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include "absl/status/statusor.h"
-
-#include <cstdlib>
-#include <utility>
-
-#include "absl/base/call_once.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/status/status.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
- : status_(std::move(status)) {}
-
-BadStatusOrAccess::BadStatusOrAccess(const BadStatusOrAccess& other)
- : status_(other.status_) {}
-
-BadStatusOrAccess& BadStatusOrAccess::operator=(
- const BadStatusOrAccess& other) {
- // Ensure assignment is correct regardless of whether this->InitWhat() has
- // already been called.
- other.InitWhat();
- status_ = other.status_;
- what_ = other.what_;
- return *this;
-}
-
-BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {
- // Ensure assignment is correct regardless of whether this->InitWhat() has
- // already been called.
- other.InitWhat();
- status_ = std::move(other.status_);
- what_ = std::move(other.what_);
- return *this;
-}
-
-BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
- : status_(std::move(other.status_)) {}
-
-const char* BadStatusOrAccess::what() const noexcept {
- InitWhat();
- return what_.c_str();
-}
-
-const absl::Status& BadStatusOrAccess::status() const { return status_; }
-
-void BadStatusOrAccess::InitWhat() const {
- absl::call_once(init_what_, [this] {
- what_ = absl::StrCat("Bad StatusOr access: ", status_.ToString());
- });
-}
-
-namespace internal_statusor {
-
-void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
- const char* kMessage =
- "An OK status is not a valid constructor argument to StatusOr<T>";
-#ifdef NDEBUG
- ABSL_INTERNAL_LOG(ERROR, kMessage);
-#else
- ABSL_INTERNAL_LOG(FATAL, kMessage);
-#endif
- // In optimized builds, we will fall back to InternalError.
- *status = absl::InternalError(kMessage);
-}
-
-void Helper::Crash(const absl::Status& status) {
- ABSL_INTERNAL_LOG(
- FATAL,
- absl::StrCat("Attempting to fetch value instead of handling error ",
- status.ToString()));
-}
-
-void ThrowBadStatusOrAccess(absl::Status status) {
-#ifdef ABSL_HAVE_EXCEPTIONS
- throw absl::BadStatusOrAccess(std::move(status));
-#else
- ABSL_INTERNAL_LOG(
- FATAL,
- absl::StrCat("Attempting to fetch value instead of handling error ",
- status.ToString()));
- std::abort();
-#endif
-}
-
-} // namespace internal_statusor
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/status/statusor.h b/third_party/abseil-cpp/absl/status/statusor.h
deleted file mode 100644
index c051fbb3aa..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor.h
+++ /dev/null
@@ -1,770 +0,0 @@
-// Copyright 2020 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: statusor.h
-// -----------------------------------------------------------------------------
-//
-// An `absl::StatusOr<T>` represents a union of an `absl::Status` object
-// and an object of type `T`. The `absl::StatusOr<T>` will either contain an
-// object of type `T` (indicating a successful operation), or an error (of type
-// `absl::Status`) explaining why such a value is not present.
-//
-// In general, check the success of an operation returning an
-// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`
-// member function.
-//
-// Example:
-//
-// StatusOr<Foo> result = Calculation();
-// if (result.ok()) {
-// result->DoSomethingCool();
-// } else {
-// LOG(ERROR) << result.status();
-// }
-#ifndef ABSL_STATUS_STATUSOR_H_
-#define ABSL_STATUS_STATUSOR_H_
-
-#include <exception>
-#include <initializer_list>
-#include <new>
-#include <string>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/attributes.h"
-#include "absl/base/call_once.h"
-#include "absl/meta/type_traits.h"
-#include "absl/status/internal/statusor_internal.h"
-#include "absl/status/status.h"
-#include "absl/types/variant.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// BadStatusOrAccess
-//
-// This class defines the type of object to throw (if exceptions are enabled),
-// when accessing the value of an `absl::StatusOr<T>` object that does not
-// contain a value. This behavior is analogous to that of
-// `std::bad_optional_access` in the case of accessing an invalid
-// `std::optional` value.
-//
-// Example:
-//
-// try {
-// absl::StatusOr<int> v = FetchInt();
-// DoWork(v.value()); // Accessing value() when not "OK" may throw
-// } catch (absl::BadStatusOrAccess& ex) {
-// LOG(ERROR) << ex.status();
-// }
-class BadStatusOrAccess : public std::exception {
- public:
- explicit BadStatusOrAccess(absl::Status status);
- ~BadStatusOrAccess() override = default;
-
- BadStatusOrAccess(const BadStatusOrAccess& other);
- BadStatusOrAccess& operator=(const BadStatusOrAccess& other);
- BadStatusOrAccess(BadStatusOrAccess&& other);
- BadStatusOrAccess& operator=(BadStatusOrAccess&& other);
-
- // BadStatusOrAccess::what()
- //
- // Returns the associated explanatory string of the `absl::StatusOr<T>`
- // object's error code. This function contains information about the failing
- // status, but its exact formatting may change and should not be depended on.
- //
- // The pointer of this string is guaranteed to be valid until any non-const
- // function is invoked on the exception object.
- const char* what() const noexcept override;
-
- // BadStatusOrAccess::status()
- //
- // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's
- // error.
- const absl::Status& status() const;
-
- private:
- void InitWhat() const;
-
- absl::Status status_;
- mutable absl::once_flag init_what_;
- mutable std::string what_;
-};
-
-// Returned StatusOr objects may not be ignored.
-template <typename T>
-class ABSL_MUST_USE_RESULT StatusOr;
-
-// absl::StatusOr<T>
-//
-// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object
-// and an object of type `T`. The `absl::StatusOr<T>` models an object that is
-// either a usable object, or an error (of type `absl::Status`) explaining why
-// such an object is not present. An `absl::StatusOr<T>` is typically the return
-// value of a function which may fail.
-//
-// An `absl::StatusOr<T>` can never hold an "OK" status (an
-// `absl::StatusCode::kOk` value); instead, the presence of an object of type
-// `T` indicates success. Instead of checking for a `kOk` value, use the
-// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code
-// readability, that using the `ok()` function is preferred for `absl::Status`
-// as well.)
-//
-// Example:
-//
-// StatusOr<Foo> result = DoBigCalculationThatCouldFail();
-// if (result.ok()) {
-// result->DoSomethingCool();
-// } else {
-// LOG(ERROR) << result.status();
-// }
-//
-// Accessing the object held by an `absl::StatusOr<T>` should be performed via
-// `operator*` or `operator->`, after a call to `ok()` confirms that the
-// `absl::StatusOr<T>` holds an object of type `T`:
-//
-// Example:
-//
-// absl::StatusOr<int> i = GetCount();
-// if (i.ok()) {
-// updated_total += *i
-// }
-//
-// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
-// throw an exception if exceptions are enabled or terminate the process when
-// exceptions are not enabled.
-//
-// Example:
-//
-// StatusOr<Foo> result = DoBigCalculationThatCouldFail();
-// const Foo& foo = result.value(); // Crash/exception if no value present
-// foo.DoSomethingCool();
-//
-// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other
-// pointer value, and the result will be that `ok()` returns `true` and
-// `value()` returns `nullptr`. Checking the value of pointer in an
-// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a
-// value is present and that value is not null:
-//
-// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
-// if (!result.ok()) {
-// LOG(ERROR) << result.status();
-// } else if (*result == nullptr) {
-// LOG(ERROR) << "Unexpected null pointer";
-// } else {
-// (*result)->DoSomethingCool();
-// }
-//
-// Example factory implementation returning StatusOr<T>:
-//
-// StatusOr<Foo> FooFactory::MakeFoo(int arg) {
-// if (arg <= 0) {
-// return absl::Status(absl::StatusCode::kInvalidArgument,
-// "Arg must be positive");
-// }
-// return Foo(arg);
-// }
-template <typename T>
-class StatusOr : private internal_statusor::StatusOrData<T>,
- private internal_statusor::CopyCtorBase<T>,
- private internal_statusor::MoveCtorBase<T>,
- private internal_statusor::CopyAssignBase<T>,
- private internal_statusor::MoveAssignBase<T> {
- template <typename U>
- friend class StatusOr;
-
- typedef internal_statusor::StatusOrData<T> Base;
-
- public:
- // StatusOr<T>::value_type
- //
- // This instance data provides a generic `value_type` member for use within
- // generic programming. This usage is analogous to that of
- // `optional::value_type` in the case of `std::optional`.
- typedef T value_type;
-
- // Constructors
-
- // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`
- // status. This constructor is marked 'explicit' to prevent usages in return
- // values such as 'return {};', under the misconception that
- // `absl::StatusOr<std::vector<int>>` will be initialized with an empty
- // vector, instead of an `absl::StatusCode::kUnknown` error code.
- explicit StatusOr();
-
- // `StatusOr<T>` is copy constructible if `T` is copy constructible.
- StatusOr(const StatusOr&) = default;
- // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy
- // assignable.
- StatusOr& operator=(const StatusOr&) = default;
-
- // `StatusOr<T>` is move constructible if `T` is move constructible.
- StatusOr(StatusOr&&) = default;
- // `StatusOr<T>` is moveAssignable if `T` is move constructible and move
- // assignable.
- StatusOr& operator=(StatusOr&&) = default;
-
- // Converting Constructors
-
- // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`
- // is constructible from `U`. To avoid ambiguity, these constructors are
- // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor
- // is explicit if and only if the corresponding construction of `T` from `U`
- // is explicit. (This constructor inherits its explicitness from the
- // underlying constructor.)
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>,
- std::is_convertible<const U&, T>,
- absl::negation<
- internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
- T, U>>>::value,
- int> = 0>
- StatusOr(const StatusOr<U>& other) // NOLINT
- : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>,
- absl::negation<std::is_convertible<const U&, T>>,
- absl::negation<
- internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
- T, U>>>::value,
- int> = 0>
- explicit StatusOr(const StatusOr<U>& other)
- : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
-
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
- std::is_convertible<U&&, T>,
- absl::negation<
- internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
- T, U>>>::value,
- int> = 0>
- StatusOr(StatusOr<U>&& other) // NOLINT
- : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
- absl::negation<std::is_convertible<U&&, T>>,
- absl::negation<
- internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
- T, U>>>::value,
- int> = 0>
- explicit StatusOr(StatusOr<U>&& other)
- : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
-
- // Converting Assignment Operators
-
- // Creates an `absl::StatusOr<T>` through assignment from an
- // `absl::StatusOr<U>` when:
- //
- // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning
- // `U` to `T` directly.
- // * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error
- // code by destroying `absl::StatusOr<T>`'s value and assigning from
- // `absl::StatusOr<U>'
- // * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is
- // OK by directly initializing `T` from `U`.
- // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error
- // code by assigning the `Status` in `absl::StatusOr<U>` to
- // `absl::StatusOr<T>`
- //
- // These overloads only apply if `absl::StatusOr<T>` is constructible and
- // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
- // assigned from `StatusOr<U>`.
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>,
- std::is_constructible<T, const U&>,
- std::is_assignable<T, const U&>,
- absl::negation<
- internal_statusor::
- IsConstructibleOrConvertibleOrAssignableFromStatusOr<
- T, U>>>::value,
- int> = 0>
- StatusOr& operator=(const StatusOr<U>& other) {
- this->Assign(other);
- return *this;
- }
- template <
- typename U,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
- std::is_assignable<T, U&&>,
- absl::negation<
- internal_statusor::
- IsConstructibleOrConvertibleOrAssignableFromStatusOr<
- T, U>>>::value,
- int> = 0>
- StatusOr& operator=(StatusOr<U>&& other) {
- this->Assign(std::move(other));
- return *this;
- }
-
- // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling
- // this constructor, `this->ok()` will be `false` and calls to `value()` will
- // crash, or produce an exception if exceptions are enabled.
- //
- // The constructor also takes any type `U` that is convertible to
- // `absl::Status`. This constructor is explicit if an only if `U` is not of
- // type `absl::Status` and the conversion from `U` to `Status` is explicit.
- //
- // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
- // In optimized builds, passing absl::OkStatus() here will have the effect
- // of passing absl::StatusCode::kInternal as a fallback.
- template <
- typename U = absl::Status,
- absl::enable_if_t<
- absl::conjunction<
- std::is_convertible<U&&, absl::Status>,
- std::is_constructible<absl::Status, U&&>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
- absl::negation<std::is_same<absl::decay_t<U>, T>>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
- absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
- T, U&&>>>::value,
- int> = 0>
- StatusOr(U&& v) : Base(std::forward<U>(v)) {}
-
- template <
- typename U = absl::Status,
- absl::enable_if_t<
- absl::conjunction<
- absl::negation<std::is_convertible<U&&, absl::Status>>,
- std::is_constructible<absl::Status, U&&>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
- absl::negation<std::is_same<absl::decay_t<U>, T>>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
- absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
- T, U&&>>>::value,
- int> = 0>
- explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
-
- template <
- typename U = absl::Status,
- absl::enable_if_t<
- absl::conjunction<
- std::is_convertible<U&&, absl::Status>,
- std::is_constructible<absl::Status, U&&>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
- absl::negation<std::is_same<absl::decay_t<U>, T>>,
- absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
- absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
- T, U&&>>>::value,
- int> = 0>
- StatusOr& operator=(U&& v) {
- this->AssignStatus(std::forward<U>(v));
- return *this;
- }
-
- // Perfect-forwarding value assignment operator.
-
- // If `*this` contains a `T` value before the call, the contained value is
- // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized
- // from `std::forward<U>(v)`.
- // This function does not participate in overload unless:
- // 1. `std::is_constructible_v<T, U>` is true,
- // 2. `std::is_assignable_v<T&, U>` is true.
- // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.
- // 4. Assigning `U` to `T` is not ambiguous:
- // If `U` is `StatusOr<V>` and `T` is constructible and assignable from
- // both `StatusOr<V>` and `V`, the assignment is considered bug-prone and
- // ambiguous thus will fail to compile. For example:
- // StatusOr<bool> s1 = true; // s1.ok() && *s1 == true
- // StatusOr<bool> s2 = false; // s2.ok() && *s2 == false
- // s1 = s2; // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?
- template <
- typename U = T,
- typename = typename std::enable_if<absl::conjunction<
- std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
- absl::disjunction<
- std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
- absl::conjunction<
- absl::negation<std::is_convertible<U&&, absl::Status>>,
- absl::negation<internal_statusor::
- HasConversionOperatorToStatusOr<T, U&&>>>>,
- internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type>
- StatusOr& operator=(U&& v) {
- this->Assign(std::forward<U>(v));
- return *this;
- }
-
- // Constructs the inner value `T` in-place using the provided args, using the
- // `T(args...)` constructor.
- template <typename... Args>
- explicit StatusOr(absl::in_place_t, Args&&... args);
- template <typename U, typename... Args>
- explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
- Args&&... args);
-
- // Constructs the inner value `T` in-place using the provided args, using the
- // `T(U)` (direct-initialization) constructor. This constructor is only valid
- // if `T` can be constructed from a `U`. Can accept move or copy constructors.
- //
- // This constructor is explicit if `U` is not convertible to `T`. To avoid
- // ambiguity, this constructor is disabled if `U` is a `StatusOr<J>`, where
- // `J` is convertible to `T`.
- template <
- typename U = T,
- absl::enable_if_t<
- absl::conjunction<
- internal_statusor::IsDirectInitializationValid<T, U&&>,
- std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
- absl::disjunction<
- std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
- T>,
- absl::conjunction<
- absl::negation<std::is_convertible<U&&, absl::Status>>,
- absl::negation<
- internal_statusor::HasConversionOperatorToStatusOr<
- T, U&&>>>>>::value,
- int> = 0>
- StatusOr(U&& u) // NOLINT
- : StatusOr(absl::in_place, std::forward<U>(u)) {}
-
- template <
- typename U = T,
- absl::enable_if_t<
- absl::conjunction<
- internal_statusor::IsDirectInitializationValid<T, U&&>,
- absl::disjunction<
- std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
- T>,
- absl::conjunction<
- absl::negation<std::is_constructible<absl::Status, U&&>>,
- absl::negation<
- internal_statusor::HasConversionOperatorToStatusOr<
- T, U&&>>>>,
- std::is_constructible<T, U&&>,
- absl::negation<std::is_convertible<U&&, T>>>::value,
- int> = 0>
- explicit StatusOr(U&& u) // NOLINT
- : StatusOr(absl::in_place, std::forward<U>(u)) {}
-
- // StatusOr<T>::ok()
- //
- // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
- // member function is analagous to `absl::Status::ok()` and should be used
- // similarly to check the status of return values.
- //
- // Example:
- //
- // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
- // if (result.ok()) {
- // // Handle result
- // else {
- // // Handle error
- // }
- ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
-
- // StatusOr<T>::status()
- //
- // Returns a reference to the current `absl::Status` contained within the
- // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
- // function returns `absl::OkStatus()`.
- const Status& status() const&;
- Status status() &&;
-
- // StatusOr<T>::value()
- //
- // Returns a reference to the held value if `this->ok()`. Otherwise, throws
- // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
- // terminate the process if exceptions are disabled.
- //
- // If you have already checked the status using `this->ok()`, you probably
- // want to use `operator*()` or `operator->()` to access the value instead of
- // `value`.
- //
- // Note: for value types that are cheap to copy, prefer simple code:
- //
- // T value = statusor.value();
- //
- // Otherwise, if the value type is expensive to copy, but can be left
- // in the StatusOr, simply assign to a reference:
- //
- // T& value = statusor.value(); // or `const T&`
- //
- // Otherwise, if the value type supports an efficient move, it can be
- // used as follows:
- //
- // T value = std::move(statusor).value();
- //
- // The `std::move` on statusor instead of on the whole expression enables
- // warnings about possible uses of the statusor object after the move.
- const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
- const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // StatusOr<T>:: operator*()
- //
- // Returns a reference to the current value.
- //
- // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
- //
- // Use `this->ok()` to verify that there is a current value within the
- // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
- // similar API that guarantees crashing or throwing an exception if there is
- // no current value.
- const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
- const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // StatusOr<T>::operator->()
- //
- // Returns a pointer to the current value.
- //
- // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
- //
- // Use `this->ok()` to verify that there is a current value.
- const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // StatusOr<T>::value_or()
- //
- // Returns the current value if `this->ok() == true`. Otherwise constructs a
- // value using the provided `default_value`.
- //
- // Unlike `value`, this function returns by value, copying the current value
- // if necessary. If the value type supports an efficient move, it can be used
- // as follows:
- //
- // T value = std::move(statusor).value_or(def);
- //
- // Unlike with `value`, calling `std::move()` on the result of `value_or` will
- // still trigger a copy.
- template <typename U>
- T value_or(U&& default_value) const&;
- template <typename U>
- T value_or(U&& default_value) &&;
-
- // StatusOr<T>::IgnoreError()
- //
- // Ignores any errors. This method does nothing except potentially suppress
- // complaints from any tools that are checking that errors are not dropped on
- // the floor.
- void IgnoreError() const;
-
- // StatusOr<T>::emplace()
- //
- // Reconstructs the inner value T in-place using the provided args, using the
- // T(args...) constructor. Returns reference to the reconstructed `T`.
- template <typename... Args>
- T& emplace(Args&&... args) {
- if (ok()) {
- this->Clear();
- this->MakeValue(std::forward<Args>(args)...);
- } else {
- this->MakeValue(std::forward<Args>(args)...);
- this->status_ = absl::OkStatus();
- }
- return this->data_;
- }
-
- template <
- typename U, typename... Args,
- absl::enable_if_t<
- std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
- int> = 0>
- T& emplace(std::initializer_list<U> ilist, Args&&... args) {
- if (ok()) {
- this->Clear();
- this->MakeValue(ilist, std::forward<Args>(args)...);
- } else {
- this->MakeValue(ilist, std::forward<Args>(args)...);
- this->status_ = absl::OkStatus();
- }
- return this->data_;
- }
-
- private:
- using internal_statusor::StatusOrData<T>::Assign;
- template <typename U>
- void Assign(const absl::StatusOr<U>& other);
- template <typename U>
- void Assign(absl::StatusOr<U>&& other);
-};
-
-// operator==()
-//
-// This operator checks the equality of two `absl::StatusOr<T>` objects.
-template <typename T>
-bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
- if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
- return lhs.status() == rhs.status();
-}
-
-// operator!=()
-//
-// This operator checks the inequality of two `absl::StatusOr<T>` objects.
-template <typename T>
-bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
- return !(lhs == rhs);
-}
-
-//------------------------------------------------------------------------------
-// Implementation details for StatusOr<T>
-//------------------------------------------------------------------------------
-
-// TODO(sbenza): avoid the string here completely.
-template <typename T>
-StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
-
-template <typename T>
-template <typename U>
-inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
- if (other.ok()) {
- this->Assign(*other);
- } else {
- this->AssignStatus(other.status());
- }
-}
-
-template <typename T>
-template <typename U>
-inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
- if (other.ok()) {
- this->Assign(*std::move(other));
- } else {
- this->AssignStatus(std::move(other).status());
- }
-}
-template <typename T>
-template <typename... Args>
-StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
- : Base(absl::in_place, std::forward<Args>(args)...) {}
-
-template <typename T>
-template <typename U, typename... Args>
-StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
- Args&&... args)
- : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
-
-template <typename T>
-const Status& StatusOr<T>::status() const& {
- return this->status_;
-}
-template <typename T>
-Status StatusOr<T>::status() && {
- return ok() ? OkStatus() : std::move(this->status_);
-}
-
-template <typename T>
-const T& StatusOr<T>::value() const& {
- if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
- return this->data_;
-}
-
-template <typename T>
-T& StatusOr<T>::value() & {
- if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
- return this->data_;
-}
-
-template <typename T>
-const T&& StatusOr<T>::value() const&& {
- if (!this->ok()) {
- internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
- }
- return std::move(this->data_);
-}
-
-template <typename T>
-T&& StatusOr<T>::value() && {
- if (!this->ok()) {
- internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
- }
- return std::move(this->data_);
-}
-
-template <typename T>
-const T& StatusOr<T>::operator*() const& {
- this->EnsureOk();
- return this->data_;
-}
-
-template <typename T>
-T& StatusOr<T>::operator*() & {
- this->EnsureOk();
- return this->data_;
-}
-
-template <typename T>
-const T&& StatusOr<T>::operator*() const&& {
- this->EnsureOk();
- return std::move(this->data_);
-}
-
-template <typename T>
-T&& StatusOr<T>::operator*() && {
- this->EnsureOk();
- return std::move(this->data_);
-}
-
-template <typename T>
-const T* StatusOr<T>::operator->() const {
- this->EnsureOk();
- return &this->data_;
-}
-
-template <typename T>
-T* StatusOr<T>::operator->() {
- this->EnsureOk();
- return &this->data_;
-}
-
-template <typename T>
-template <typename U>
-T StatusOr<T>::value_or(U&& default_value) const& {
- if (ok()) {
- return this->data_;
- }
- return std::forward<U>(default_value);
-}
-
-template <typename T>
-template <typename U>
-T StatusOr<T>::value_or(U&& default_value) && {
- if (ok()) {
- return std::move(this->data_);
- }
- return std::forward<U>(default_value);
-}
-
-template <typename T>
-void StatusOr<T>::IgnoreError() const {
- // no-op
-}
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STATUS_STATUSOR_H_
diff --git a/third_party/abseil-cpp/absl/status/statusor_test.cc b/third_party/abseil-cpp/absl/status/statusor_test.cc
deleted file mode 100644
index 7cae90e185..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor_test.cc
+++ /dev/null
@@ -1,1847 +0,0 @@
-// Copyright 2020 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/status/statusor.h"
-
-#include <array>
-#include <initializer_list>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/casts.h"
-#include "absl/memory/memory.h"
-#include "absl/status/status.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/any.h"
-#include "absl/utility/utility.h"
-
-namespace {
-
-using ::testing::AllOf;
-using ::testing::AnyWith;
-using ::testing::ElementsAre;
-using ::testing::Field;
-using ::testing::HasSubstr;
-using ::testing::Ne;
-using ::testing::Not;
-using ::testing::Pointee;
-using ::testing::VariantWith;
-
-#ifdef GTEST_HAS_STATUS_MATCHERS
-using ::testing::status::IsOk;
-using ::testing::status::IsOkAndHolds;
-#else // GTEST_HAS_STATUS_MATCHERS
-inline const ::absl::Status& GetStatus(const ::absl::Status& status) {
- return status;
-}
-
-template <typename T>
-inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) {
- return status.status();
-}
-
-// Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a
-// reference to StatusOr<T>.
-template <typename StatusOrType>
-class IsOkAndHoldsMatcherImpl
- : public ::testing::MatcherInterface<StatusOrType> {
- public:
- typedef
- typename std::remove_reference<StatusOrType>::type::value_type value_type;
-
- template <typename InnerMatcher>
- explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
- : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
- std::forward<InnerMatcher>(inner_matcher))) {}
-
- void DescribeTo(std::ostream* os) const override {
- *os << "is OK and has a value that ";
- inner_matcher_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "isn't OK or has a value that ";
- inner_matcher_.DescribeNegationTo(os);
- }
-
- bool MatchAndExplain(
- StatusOrType actual_value,
- ::testing::MatchResultListener* result_listener) const override {
- if (!actual_value.ok()) {
- *result_listener << "which has status " << actual_value.status();
- return false;
- }
-
- ::testing::StringMatchResultListener inner_listener;
- const bool matches =
- inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
- const std::string inner_explanation = inner_listener.str();
- if (!inner_explanation.empty()) {
- *result_listener << "which contains value "
- << ::testing::PrintToString(*actual_value) << ", "
- << inner_explanation;
- }
- return matches;
- }
-
- private:
- const ::testing::Matcher<const value_type&> inner_matcher_;
-};
-
-// Implements IsOkAndHolds(m) as a polymorphic matcher.
-template <typename InnerMatcher>
-class IsOkAndHoldsMatcher {
- public:
- explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
- : inner_matcher_(std::move(inner_matcher)) {}
-
- // Converts this polymorphic matcher to a monomorphic matcher of the
- // given type. StatusOrType can be either StatusOr<T> or a
- // reference to StatusOr<T>.
- template <typename StatusOrType>
- operator ::testing::Matcher<StatusOrType>() const { // NOLINT
- return ::testing::Matcher<StatusOrType>(
- new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
- }
-
- private:
- const InnerMatcher inner_matcher_;
-};
-
-// Monomorphic implementation of matcher IsOk() for a given type T.
-// T can be Status, StatusOr<>, or a reference to either of them.
-template <typename T>
-class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
- public:
- void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "is not OK";
- }
- bool MatchAndExplain(T actual_value,
- ::testing::MatchResultListener*) const override {
- return GetStatus(actual_value).ok();
- }
-};
-
-// Implements IsOk() as a polymorphic matcher.
-class IsOkMatcher {
- public:
- template <typename T>
- operator ::testing::Matcher<T>() const { // NOLINT
- return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>());
- }
-};
-
-// Macros for testing the results of functions that return absl::Status or
-// absl::StatusOr<T> (for any type T).
-#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk())
-
-// Returns a gMock matcher that matches a StatusOr<> whose status is
-// OK and whose value matches the inner matcher.
-template <typename InnerMatcher>
-IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds(
- InnerMatcher&& inner_matcher) {
- return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
- std::forward<InnerMatcher>(inner_matcher));
-}
-
-// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.
-inline IsOkMatcher IsOk() { return IsOkMatcher(); }
-#endif // GTEST_HAS_STATUS_MATCHERS
-
-struct CopyDetector {
- CopyDetector() = default;
- explicit CopyDetector(int xx) : x(xx) {}
- CopyDetector(CopyDetector&& d) noexcept
- : x(d.x), copied(false), moved(true) {}
- CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
- CopyDetector& operator=(const CopyDetector& c) {
- x = c.x;
- copied = true;
- moved = false;
- return *this;
- }
- CopyDetector& operator=(CopyDetector&& c) noexcept {
- x = c.x;
- copied = false;
- moved = true;
- return *this;
- }
- int x = 0;
- bool copied = false;
- bool moved = false;
-};
-
-testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {
- return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),
- Field(&CopyDetector::copied, c));
-}
-
-class Base1 {
- public:
- virtual ~Base1() {}
- int pad;
-};
-
-class Base2 {
- public:
- virtual ~Base2() {}
- int yetotherpad;
-};
-
-class Derived : public Base1, public Base2 {
- public:
- virtual ~Derived() {}
- int evenmorepad;
-};
-
-class CopyNoAssign {
- public:
- explicit CopyNoAssign(int value) : foo(value) {}
- CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
- int foo;
-
- private:
- const CopyNoAssign& operator=(const CopyNoAssign&);
-};
-
-absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
- // Uses implicit constructor from T&&
- return absl::make_unique<int>(0);
-}
-
-TEST(StatusOr, ElementType) {
- static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), "");
- static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), "");
-}
-
-TEST(StatusOr, TestMoveOnlyInitialization) {
- absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
- ASSERT_TRUE(thing.ok());
- EXPECT_EQ(0, **thing);
- int* previous = thing->get();
-
- thing = ReturnUniquePtr();
- EXPECT_TRUE(thing.ok());
- EXPECT_EQ(0, **thing);
- EXPECT_NE(previous, thing->get());
-}
-
-TEST(StatusOr, TestMoveOnlyValueExtraction) {
- absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
- ASSERT_TRUE(thing.ok());
- std::unique_ptr<int> ptr = *std::move(thing);
- EXPECT_EQ(0, *ptr);
-
- thing = std::move(ptr);
- ptr = std::move(*thing);
- EXPECT_EQ(0, *ptr);
-}
-
-TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
- std::unique_ptr<int> ptr(*ReturnUniquePtr());
- EXPECT_EQ(0, *ptr);
-}
-
-TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {
- static_assert(
- std::is_same<
- const int&&,
- decltype(std::declval<const absl::StatusOr<int>&&>().value())>(),
- "value() for const temporaries should return const T&&");
-}
-
-TEST(StatusOr, TestMoveOnlyConversion) {
- absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
- EXPECT_TRUE(const_thing.ok());
- EXPECT_EQ(0, **const_thing);
-
- // Test rvalue converting assignment
- const int* const_previous = const_thing->get();
- const_thing = ReturnUniquePtr();
- EXPECT_TRUE(const_thing.ok());
- EXPECT_EQ(0, **const_thing);
- EXPECT_NE(const_previous, const_thing->get());
-}
-
-TEST(StatusOr, TestMoveOnlyVector) {
- // Sanity check that absl::StatusOr<MoveOnly> works in vector.
- std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;
- vec.push_back(ReturnUniquePtr());
- vec.resize(2);
- auto another_vec = std::move(vec);
- EXPECT_EQ(0, **another_vec[0]);
- EXPECT_EQ(absl::UnknownError(""), another_vec[1].status());
-}
-
-TEST(StatusOr, TestDefaultCtor) {
- absl::StatusOr<int> thing;
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
-}
-
-TEST(StatusOr, StatusCtorForwards) {
- absl::Status status(absl::StatusCode::kInternal, "Some error");
-
- EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error");
- EXPECT_EQ(status.message(), "Some error");
-
- EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),
- "Some error");
- EXPECT_NE(status.message(), "Some error");
-}
-
-TEST(BadStatusOrAccessTest, CopyConstructionWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{e1};
- EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, CopyAssignmentWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{absl::InternalError("other")};
- e2 = e1;
- EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, MoveConstructionWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{std::move(e1)};
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, MoveAssignmentWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{absl::InternalError("other")};
- e2 = std::move(e1);
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,
-// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether
-// exceptions are enabled.
-#ifdef ABSL_HAVE_EXCEPTIONS
-#define EXPECT_DEATH_OR_THROW(statement, status_) \
- EXPECT_THROW( \
- { \
- try { \
- statement; \
- } catch (const absl::BadStatusOrAccess& e) { \
- EXPECT_EQ(e.status(), status_); \
- EXPECT_THAT(e.what(), HasSubstr(e.status().ToString())); \
- throw; \
- } \
- }, \
- absl::BadStatusOrAccess);
-#else // ABSL_HAVE_EXCEPTIONS
-#define EXPECT_DEATH_OR_THROW(statement, status) \
- EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());
-#endif // ABSL_HAVE_EXCEPTIONS
-
-TEST(StatusOrDeathTest, TestDefaultCtorValue) {
- absl::StatusOr<int> thing;
- EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
- const absl::StatusOr<int> thing2;
- EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(""));
-}
-
-TEST(StatusOrDeathTest, TestValueNotOk) {
- absl::StatusOr<int> thing(absl::CancelledError());
- EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
-}
-
-TEST(StatusOrDeathTest, TestValueNotOkConst) {
- const absl::StatusOr<int> thing(absl::UnknownError(""));
- EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
-}
-
-TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
- absl::StatusOr<int*> thing;
- EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
-}
-
-TEST(StatusOrDeathTest, TestPointerValueNotOk) {
- absl::StatusOr<int*> thing(absl::CancelledError());
- EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
-}
-
-TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
- const absl::StatusOr<int*> thing(absl::CancelledError());
- EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
-}
-
-#if GTEST_HAS_DEATH_TEST
-TEST(StatusOrDeathTest, TestStatusCtorStatusOk) {
- EXPECT_DEBUG_DEATH(
- {
- // This will DCHECK
- absl::StatusOr<int> thing(absl::OkStatus());
- // In optimized mode, we are actually going to get error::INTERNAL for
- // status here, rather than crashing, so check that.
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
- },
- "An OK status is not a valid constructor argument");
-}
-
-TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {
- EXPECT_DEBUG_DEATH(
- {
- absl::StatusOr<int*> thing(absl::OkStatus());
- // In optimized mode, we are actually going to get error::INTERNAL for
- // status here, rather than crashing, so check that.
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
- },
- "An OK status is not a valid constructor argument");
-}
-#endif
-
-TEST(StatusOr, ValueAccessor) {
- const int kIntValue = 110;
- {
- absl::StatusOr<int> status_or(kIntValue);
- EXPECT_EQ(kIntValue, status_or.value());
- EXPECT_EQ(kIntValue, std::move(status_or).value());
- }
- {
- absl::StatusOr<CopyDetector> status_or(kIntValue);
- EXPECT_THAT(status_or,
- IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));
- CopyDetector copy_detector = status_or.value();
- EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));
- copy_detector = std::move(status_or).value();
- EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));
- }
-}
-
-TEST(StatusOr, BadValueAccess) {
- const absl::Status kError = absl::CancelledError("message");
- absl::StatusOr<int> status_or(kError);
- EXPECT_DEATH_OR_THROW(status_or.value(), kError);
-}
-
-TEST(StatusOr, TestStatusCtor) {
- absl::StatusOr<int> thing(absl::CancelledError());
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestValueCtor) {
- const int kI = 4;
- const absl::StatusOr<int> thing(kI);
- EXPECT_TRUE(thing.ok());
- EXPECT_EQ(kI, *thing);
-}
-
-struct Foo {
- const int x;
- explicit Foo(int y) : x(y) {}
-};
-
-TEST(StatusOr, InPlaceConstruction) {
- EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),
- IsOkAndHolds(Field(&Foo::x, 10)));
-}
-
-struct InPlaceHelper {
- InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
- : x(xs), y(std::move(yy)) {}
- const std::vector<int> x;
- std::unique_ptr<int> y;
-};
-
-TEST(StatusOr, InPlaceInitListConstruction) {
- absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
- absl::make_unique<int>(13));
- EXPECT_THAT(status_or, IsOkAndHolds(AllOf(
- Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),
- Field(&InPlaceHelper::y, Pointee(13)))));
-}
-
-TEST(StatusOr, Emplace) {
- absl::StatusOr<Foo> status_or_foo(10);
- status_or_foo.emplace(20);
- EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
- status_or_foo = absl::InvalidArgumentError("msg");
- EXPECT_FALSE(status_or_foo.ok());
- EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);
- EXPECT_EQ(status_or_foo.status().message(), "msg");
- status_or_foo.emplace(20);
- EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
-}
-
-TEST(StatusOr, EmplaceInitializerList) {
- absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
- absl::make_unique<int>(13));
- status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
- EXPECT_THAT(status_or,
- IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
- Field(&InPlaceHelper::y, Pointee(4)))));
- status_or = absl::InvalidArgumentError("msg");
- EXPECT_FALSE(status_or.ok());
- EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);
- EXPECT_EQ(status_or.status().message(), "msg");
- status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
- EXPECT_THAT(status_or,
- IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
- Field(&InPlaceHelper::y, Pointee(4)))));
-}
-
-TEST(StatusOr, TestCopyCtorStatusOk) {
- const int kI = 4;
- const absl::StatusOr<int> original(kI);
- const absl::StatusOr<int> copy(original);
- EXPECT_OK(copy.status());
- EXPECT_EQ(*original, *copy);
-}
-
-TEST(StatusOr, TestCopyCtorStatusNotOk) {
- absl::StatusOr<int> original(absl::CancelledError());
- absl::StatusOr<int> copy(original);
- EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestCopyCtorNonAssignable) {
- const int kI = 4;
- CopyNoAssign value(kI);
- absl::StatusOr<CopyNoAssign> original(value);
- absl::StatusOr<CopyNoAssign> copy(original);
- EXPECT_OK(copy.status());
- EXPECT_EQ(original->foo, copy->foo);
-}
-
-TEST(StatusOr, TestCopyCtorStatusOKConverting) {
- const int kI = 4;
- absl::StatusOr<int> original(kI);
- absl::StatusOr<double> copy(original);
- EXPECT_OK(copy.status());
- EXPECT_DOUBLE_EQ(*original, *copy);
-}
-
-TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
- absl::StatusOr<int> original(absl::CancelledError());
- absl::StatusOr<double> copy(original);
- EXPECT_EQ(copy.status(), original.status());
-}
-
-TEST(StatusOr, TestAssignmentStatusOk) {
- // Copy assignmment
- {
- const auto p = std::make_shared<int>(17);
- absl::StatusOr<std::shared_ptr<int>> source(p);
-
- absl::StatusOr<std::shared_ptr<int>> target;
- target = source;
-
- ASSERT_TRUE(target.ok());
- EXPECT_OK(target.status());
- EXPECT_EQ(p, *target);
-
- ASSERT_TRUE(source.ok());
- EXPECT_OK(source.status());
- EXPECT_EQ(p, *source);
- }
-
- // Move asssignment
- {
- const auto p = std::make_shared<int>(17);
- absl::StatusOr<std::shared_ptr<int>> source(p);
-
- absl::StatusOr<std::shared_ptr<int>> target;
- target = std::move(source);
-
- ASSERT_TRUE(target.ok());
- EXPECT_OK(target.status());
- EXPECT_EQ(p, *target);
-
- ASSERT_TRUE(source.ok());
- EXPECT_OK(source.status());
- EXPECT_EQ(nullptr, *source);
- }
-}
-
-TEST(StatusOr, TestAssignmentStatusNotOk) {
- // Copy assignment
- {
- const absl::Status expected = absl::CancelledError();
- absl::StatusOr<int> source(expected);
-
- absl::StatusOr<int> target;
- target = source;
-
- EXPECT_FALSE(target.ok());
- EXPECT_EQ(expected, target.status());
-
- EXPECT_FALSE(source.ok());
- EXPECT_EQ(expected, source.status());
- }
-
- // Move assignment
- {
- const absl::Status expected = absl::CancelledError();
- absl::StatusOr<int> source(expected);
-
- absl::StatusOr<int> target;
- target = std::move(source);
-
- EXPECT_FALSE(target.ok());
- EXPECT_EQ(expected, target.status());
-
- EXPECT_FALSE(source.ok());
- EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
- }
-}
-
-TEST(StatusOr, TestAssignmentStatusOKConverting) {
- // Copy assignment
- {
- const int kI = 4;
- absl::StatusOr<int> source(kI);
-
- absl::StatusOr<double> target;
- target = source;
-
- ASSERT_TRUE(target.ok());
- EXPECT_OK(target.status());
- EXPECT_DOUBLE_EQ(kI, *target);
-
- ASSERT_TRUE(source.ok());
- EXPECT_OK(source.status());
- EXPECT_DOUBLE_EQ(kI, *source);
- }
-
- // Move assignment
- {
- const auto p = new int(17);
- absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));
-
- absl::StatusOr<std::shared_ptr<int>> target;
- target = std::move(source);
-
- ASSERT_TRUE(target.ok());
- EXPECT_OK(target.status());
- EXPECT_EQ(p, target->get());
-
- ASSERT_TRUE(source.ok());
- EXPECT_OK(source.status());
- EXPECT_EQ(nullptr, source->get());
- }
-}
-
-struct A {
- int x;
-};
-
-struct ImplicitConstructibleFromA {
- int x;
- bool moved;
- ImplicitConstructibleFromA(const A& a) // NOLINT
- : x(a.x), moved(false) {}
- ImplicitConstructibleFromA(A&& a) // NOLINT
- : x(a.x), moved(true) {}
-};
-
-TEST(StatusOr, ImplicitConvertingConstructor) {
- EXPECT_THAT(
- absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(
- absl::StatusOr<A>(A{11})),
- IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),
- Field(&ImplicitConstructibleFromA::moved, true))));
- absl::StatusOr<A> a(A{12});
- EXPECT_THAT(
- absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),
- IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),
- Field(&ImplicitConstructibleFromA::moved, false))));
-}
-
-struct ExplicitConstructibleFromA {
- int x;
- bool moved;
- explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
- explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
-};
-
-TEST(StatusOr, ExplicitConvertingConstructor) {
- EXPECT_FALSE(
- (std::is_convertible<const absl::StatusOr<A>&,
- absl::StatusOr<ExplicitConstructibleFromA>>::value));
- EXPECT_FALSE(
- (std::is_convertible<absl::StatusOr<A>&&,
- absl::StatusOr<ExplicitConstructibleFromA>>::value));
- EXPECT_THAT(
- absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),
- IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),
- Field(&ExplicitConstructibleFromA::moved, true))));
- absl::StatusOr<A> a(A{12});
- EXPECT_THAT(
- absl::StatusOr<ExplicitConstructibleFromA>(a),
- IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),
- Field(&ExplicitConstructibleFromA::moved, false))));
-}
-
-struct ImplicitConstructibleFromBool {
- ImplicitConstructibleFromBool(bool y) : x(y) {} // NOLINT
- bool x = false;
-};
-
-struct ConvertibleToBool {
- explicit ConvertibleToBool(bool y) : x(y) {}
- operator bool() const { return x; } // NOLINT
- bool x = false;
-};
-
-TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
- IsOkAndHolds(false));
- EXPECT_THAT(
- absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(
- absl::StatusOr<bool>(false)),
- IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
- EXPECT_FALSE((std::is_convertible<
- absl::StatusOr<ConvertibleToBool>,
- absl::StatusOr<ImplicitConstructibleFromBool>>::value));
-}
-
-TEST(StatusOr, BooleanConstructionWithImplicitCasts) {
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
- IsOkAndHolds(false));
- EXPECT_THAT(
- absl::StatusOr<ImplicitConstructibleFromBool>{
- absl::StatusOr<bool>(false)},
- IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
- EXPECT_THAT(
- absl::StatusOr<ImplicitConstructibleFromBool>{
- absl::StatusOr<bool>(absl::InvalidArgumentError(""))},
- Not(IsOk()));
-
- EXPECT_THAT(
- absl::StatusOr<ImplicitConstructibleFromBool>{
- absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},
- IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
- EXPECT_THAT(
- absl::StatusOr<ImplicitConstructibleFromBool>{
- absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))},
- Not(IsOk()));
-}
-
-TEST(StatusOr, ConstImplicitCast) {
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
- absl::StatusOr<const bool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
- absl::StatusOr<const bool>(false)),
- IsOkAndHolds(false));
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
- absl::StatusOr<bool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
- absl::StatusOr<bool>(false)),
- IsOkAndHolds(false));
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(
- absl::StatusOr<std::string>("foo")),
- IsOkAndHolds("foo"));
- EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(
- absl::StatusOr<const std::string>("foo")),
- IsOkAndHolds("foo"));
- EXPECT_THAT(
- absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(
- absl::StatusOr<std::shared_ptr<std::string>>(
- std::make_shared<std::string>("foo"))),
- IsOkAndHolds(Pointee(std::string("foo"))));
-}
-
-TEST(StatusOr, ConstExplicitConstruction) {
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),
- IsOkAndHolds(false));
- EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),
- IsOkAndHolds(true));
- EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),
- IsOkAndHolds(false));
-}
-
-struct ExplicitConstructibleFromInt {
- int x;
- explicit ExplicitConstructibleFromInt(int y) : x(y) {}
-};
-
-TEST(StatusOr, ExplicitConstruction) {
- EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),
- IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));
-}
-
-TEST(StatusOr, ImplicitConstruction) {
- // Check implicit casting works.
- auto status_or =
- absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10);
- EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
-}
-
-TEST(StatusOr, ImplicitConstructionFromInitliazerList) {
- // Note: dropping the explicit std::initializer_list<int> is not supported
- // by absl::StatusOr or absl::optional.
- auto status_or =
- absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});
- EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
-}
-
-TEST(StatusOr, UniquePtrImplicitConstruction) {
- auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(
- absl::make_unique<Derived>());
- EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
-}
-
-TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {
- absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
- absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
- absl::InvalidArgumentError("foo");
- EXPECT_THAT(status_or,
- IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
- absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;
- EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
- absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;
- EXPECT_THAT(a_err, Not(IsOk()));
-
- const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
- absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref; // NOLINT
- EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
- const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
- absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err; // NOLINT
- EXPECT_THAT(b_err, Not(IsOk()));
-
- absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);
- EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
- absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);
- EXPECT_THAT(c_err, Not(IsOk()));
-}
-
-TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {
- absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
- absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
- absl::InvalidArgumentError("foo");
- absl::StatusOr<absl::StatusOr<CopyDetector>> a;
- a = status_or;
- EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
- a = status_error;
- EXPECT_THAT(a, Not(IsOk()));
-
- const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
- a = cref;
- EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
- const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
- a = cref_err;
- EXPECT_THAT(a, Not(IsOk()));
- a = std::move(status_or);
- EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
- a = std::move(status_error);
- EXPECT_THAT(a, Not(IsOk()));
-}
-
-struct Copyable {
- Copyable() {}
- Copyable(const Copyable&) {}
- Copyable& operator=(const Copyable&) { return *this; }
-};
-
-struct MoveOnly {
- MoveOnly() {}
- MoveOnly(MoveOnly&&) {}
- MoveOnly& operator=(MoveOnly&&) { return *this; }
-};
-
-struct NonMovable {
- NonMovable() {}
- NonMovable(const NonMovable&) = delete;
- NonMovable(NonMovable&&) = delete;
- NonMovable& operator=(const NonMovable&) = delete;
- NonMovable& operator=(NonMovable&&) = delete;
-};
-
-TEST(StatusOr, CopyAndMoveAbility) {
- EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
- EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
- EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
- EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
- EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
- EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
- EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
- EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
- EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
- EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
- EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
- EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
-}
-
-TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {
- absl::StatusOr<absl::any> status_or = CopyDetector(10);
- absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
- EXPECT_THAT(
- status_or,
- IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
- absl::StatusOr<absl::any> a = status_or;
- EXPECT_THAT(
- a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
- absl::StatusOr<absl::any> a_err = status_error;
- EXPECT_THAT(a_err, Not(IsOk()));
-
- const absl::StatusOr<absl::any>& cref = status_or;
- // No lint for no-change copy.
- absl::StatusOr<absl::any> b = cref; // NOLINT
- EXPECT_THAT(
- b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
- const absl::StatusOr<absl::any>& cref_err = status_error;
- // No lint for no-change copy.
- absl::StatusOr<absl::any> b_err = cref_err; // NOLINT
- EXPECT_THAT(b_err, Not(IsOk()));
-
- absl::StatusOr<absl::any> c = std::move(status_or);
- EXPECT_THAT(
- c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
- absl::StatusOr<absl::any> c_err = std::move(status_error);
- EXPECT_THAT(c_err, Not(IsOk()));
-}
-
-TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {
- absl::StatusOr<absl::any> status_or = CopyDetector(10);
- absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
- absl::StatusOr<absl::any> a;
- a = status_or;
- EXPECT_THAT(
- a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
- a = status_error;
- EXPECT_THAT(a, Not(IsOk()));
-
- const absl::StatusOr<absl::any>& cref = status_or;
- a = cref;
- EXPECT_THAT(
- a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
- const absl::StatusOr<absl::any>& cref_err = status_error;
- a = cref_err;
- EXPECT_THAT(a, Not(IsOk()));
- a = std::move(status_or);
- EXPECT_THAT(
- a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
- a = std::move(status_error);
- EXPECT_THAT(a, Not(IsOk()));
-}
-
-TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {
- absl::StatusOr<CopyDetector> status_or(10);
- ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
- absl::StatusOr<CopyDetector> a(status_or);
- EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
- const absl::StatusOr<CopyDetector>& cref = status_or;
- absl::StatusOr<CopyDetector> b(cref); // NOLINT
- EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
- absl::StatusOr<CopyDetector> c(std::move(status_or));
- EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
-}
-
-TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {
- absl::StatusOr<CopyDetector> status_or(10);
- ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
- absl::StatusOr<CopyDetector> a;
- a = status_or;
- EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
- const absl::StatusOr<CopyDetector>& cref = status_or;
- absl::StatusOr<CopyDetector> b;
- b = cref;
- EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
- absl::StatusOr<CopyDetector> c;
- c = std::move(status_or);
- EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
-}
-
-TEST(StatusOr, AbslAnyAssignment) {
- EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>,
- absl::StatusOr<int>>::value));
- absl::StatusOr<absl::any> status_or;
- status_or = absl::InvalidArgumentError("foo");
- EXPECT_THAT(status_or, Not(IsOk()));
-}
-
-TEST(StatusOr, ImplicitAssignment) {
- absl::StatusOr<absl::variant<int, std::string>> status_or;
- status_or = 10;
- EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
-}
-
-TEST(StatusOr, SelfDirectInitAssignment) {
- absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
- status_or = *status_or;
- EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
-}
-
-TEST(StatusOr, ImplicitCastFromInitializerList) {
- absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
- EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
-}
-
-TEST(StatusOr, UniquePtrImplicitAssignment) {
- absl::StatusOr<std::unique_ptr<Base1>> status_or;
- status_or = absl::make_unique<Derived>();
- EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
-}
-
-TEST(StatusOr, Pointer) {
- struct A {};
- struct B : public A {};
- struct C : private A {};
-
- EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));
- EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));
- EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));
- EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));
-}
-
-TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
- // Copy assignment
- {
- const absl::Status expected = absl::CancelledError();
- absl::StatusOr<int> source(expected);
-
- absl::StatusOr<double> target;
- target = source;
-
- EXPECT_FALSE(target.ok());
- EXPECT_EQ(expected, target.status());
-
- EXPECT_FALSE(source.ok());
- EXPECT_EQ(expected, source.status());
- }
-
- // Move assignment
- {
- const absl::Status expected = absl::CancelledError();
- absl::StatusOr<int> source(expected);
-
- absl::StatusOr<double> target;
- target = std::move(source);
-
- EXPECT_FALSE(target.ok());
- EXPECT_EQ(expected, target.status());
-
- EXPECT_FALSE(source.ok());
- EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
- }
-}
-
-TEST(StatusOr, SelfAssignment) {
- // Copy-assignment, status OK
- {
- // A string long enough that it's likely to defeat any inline representation
- // optimization.
- const std::string long_str(128, 'a');
-
- absl::StatusOr<std::string> so = long_str;
- so = *&so;
-
- ASSERT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(long_str, *so);
- }
-
- // Copy-assignment, error status
- {
- absl::StatusOr<int> so = absl::NotFoundError("taco");
- so = *&so;
-
- EXPECT_FALSE(so.ok());
- EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
- EXPECT_EQ(so.status().message(), "taco");
- }
-
- // Move-assignment with copyable type, status OK
- {
- absl::StatusOr<int> so = 17;
-
- // Fool the compiler, which otherwise complains.
- auto& same = so;
- so = std::move(same);
-
- ASSERT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(17, *so);
- }
-
- // Move-assignment with copyable type, error status
- {
- absl::StatusOr<int> so = absl::NotFoundError("taco");
-
- // Fool the compiler, which otherwise complains.
- auto& same = so;
- so = std::move(same);
-
- EXPECT_FALSE(so.ok());
- EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
- EXPECT_EQ(so.status().message(), "taco");
- }
-
- // Move-assignment with non-copyable type, status OK
- {
- const auto raw = new int(17);
- absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);
-
- // Fool the compiler, which otherwise complains.
- auto& same = so;
- so = std::move(same);
-
- ASSERT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(raw, so->get());
- }
-
- // Move-assignment with non-copyable type, error status
- {
- absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco");
-
- // Fool the compiler, which otherwise complains.
- auto& same = so;
- so = std::move(same);
-
- EXPECT_FALSE(so.ok());
- EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
- EXPECT_EQ(so.status().message(), "taco");
- }
-}
-
-// These types form the overload sets of the constructors and the assignment
-// operators of `MockValue`. They distinguish construction from assignment,
-// lvalue from rvalue.
-struct FromConstructibleAssignableLvalue {};
-struct FromConstructibleAssignableRvalue {};
-struct FromImplicitConstructibleOnly {};
-struct FromAssignableOnly {};
-
-// This class is for testing the forwarding value assignments of `StatusOr`.
-// `from_rvalue` indicates whether the constructor or the assignment taking
-// rvalue reference is called. `from_assignment` indicates whether any
-// assignment is called.
-struct MockValue {
- // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
- MockValue(const FromConstructibleAssignableLvalue&) // NOLINT
- : from_rvalue(false), assigned(false) {}
- // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
- MockValue(FromConstructibleAssignableRvalue&&) // NOLINT
- : from_rvalue(true), assigned(false) {}
- // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
- // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
- MockValue(const FromImplicitConstructibleOnly&) // NOLINT
- : from_rvalue(false), assigned(false) {}
- // Assigns `FromConstructibleAssignableLvalue`.
- MockValue& operator=(const FromConstructibleAssignableLvalue&) {
- from_rvalue = false;
- assigned = true;
- return *this;
- }
- // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
- MockValue& operator=(FromConstructibleAssignableRvalue&&) {
- from_rvalue = true;
- assigned = true;
- return *this;
- }
- // Assigns `FromAssignableOnly`, but not constructible from
- // `FromAssignableOnly`.
- MockValue& operator=(const FromAssignableOnly&) {
- from_rvalue = false;
- assigned = true;
- return *this;
- }
- bool from_rvalue;
- bool assigned;
-};
-
-// operator=(U&&)
-TEST(StatusOr, PerfectForwardingAssignment) {
- // U == T
- constexpr int kValue1 = 10, kValue2 = 20;
- absl::StatusOr<CopyDetector> status_or;
- CopyDetector lvalue(kValue1);
- status_or = lvalue;
- EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));
- status_or = CopyDetector(kValue2);
- EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));
-
- // U != T
- EXPECT_TRUE(
- (std::is_assignable<absl::StatusOr<MockValue>&,
- const FromConstructibleAssignableLvalue&>::value));
- EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
- FromConstructibleAssignableLvalue&&>::value));
- EXPECT_FALSE(
- (std::is_assignable<absl::StatusOr<MockValue>&,
- const FromConstructibleAssignableRvalue&>::value));
- EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
- FromConstructibleAssignableRvalue&&>::value));
- EXPECT_TRUE(
- (std::is_assignable<absl::StatusOr<MockValue>&,
- const FromImplicitConstructibleOnly&>::value));
- EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,
- const FromAssignableOnly&>::value));
-
- absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
- EXPECT_FALSE(from_lvalue->from_rvalue);
- EXPECT_FALSE(from_lvalue->assigned);
- from_lvalue = FromConstructibleAssignableLvalue{};
- EXPECT_FALSE(from_lvalue->from_rvalue);
- EXPECT_TRUE(from_lvalue->assigned);
-
- absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
- EXPECT_TRUE(from_rvalue->from_rvalue);
- EXPECT_FALSE(from_rvalue->assigned);
- from_rvalue = FromConstructibleAssignableRvalue{};
- EXPECT_TRUE(from_rvalue->from_rvalue);
- EXPECT_TRUE(from_rvalue->assigned);
-
- absl::StatusOr<MockValue> from_implicit_constructible(
- FromImplicitConstructibleOnly{});
- EXPECT_FALSE(from_implicit_constructible->from_rvalue);
- EXPECT_FALSE(from_implicit_constructible->assigned);
- // construct a temporary `StatusOr` object and invoke the `StatusOr` move
- // assignment operator.
- from_implicit_constructible = FromImplicitConstructibleOnly{};
- EXPECT_FALSE(from_implicit_constructible->from_rvalue);
- EXPECT_FALSE(from_implicit_constructible->assigned);
-}
-
-TEST(StatusOr, TestStatus) {
- absl::StatusOr<int> good(4);
- EXPECT_TRUE(good.ok());
- absl::StatusOr<int> bad(absl::CancelledError());
- EXPECT_FALSE(bad.ok());
- EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, OperatorStarRefQualifiers) {
- static_assert(
- std::is_same<const int&,
- decltype(*std::declval<const absl::StatusOr<int>&>())>(),
- "Unexpected ref-qualifiers");
- static_assert(
- std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),
- "Unexpected ref-qualifiers");
- static_assert(
- std::is_same<const int&&,
- decltype(*std::declval<const absl::StatusOr<int>&&>())>(),
- "Unexpected ref-qualifiers");
- static_assert(
- std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),
- "Unexpected ref-qualifiers");
-}
-
-TEST(StatusOr, OperatorStar) {
- const absl::StatusOr<std::string> const_lvalue("hello");
- EXPECT_EQ("hello", *const_lvalue);
-
- absl::StatusOr<std::string> lvalue("hello");
- EXPECT_EQ("hello", *lvalue);
-
- // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
- // reference type.
- const absl::StatusOr<std::string> const_rvalue("hello");
- EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT
-
- absl::StatusOr<std::string> rvalue("hello");
- EXPECT_EQ("hello", *std::move(rvalue));
-}
-
-TEST(StatusOr, OperatorArrowQualifiers) {
- static_assert(
- std::is_same<
- const int*,
- decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),
- "Unexpected qualifiers");
- static_assert(
- std::is_same<
- int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),
- "Unexpected qualifiers");
- static_assert(
- std::is_same<
- const int*,
- decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),
- "Unexpected qualifiers");
- static_assert(
- std::is_same<
- int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),
- "Unexpected qualifiers");
-}
-
-TEST(StatusOr, OperatorArrow) {
- const absl::StatusOr<std::string> const_lvalue("hello");
- EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
-
- absl::StatusOr<std::string> lvalue("hello");
- EXPECT_EQ(std::string("hello"), lvalue->c_str());
-}
-
-TEST(StatusOr, RValueStatus) {
- absl::StatusOr<int> so(absl::NotFoundError("taco"));
- const absl::Status s = std::move(so).status();
-
- EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);
- EXPECT_EQ(s.message(), "taco");
-
- // Check that !ok() still implies !status().ok(), even after moving out of the
- // object. See the note on the rvalue ref-qualified status method.
- EXPECT_FALSE(so.ok()); // NOLINT
- EXPECT_FALSE(so.status().ok());
- EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);
- EXPECT_EQ(so.status().message(), "Status accessed after move.");
-}
-
-TEST(StatusOr, TestValue) {
- const int kI = 4;
- absl::StatusOr<int> thing(kI);
- EXPECT_EQ(kI, *thing);
-}
-
-TEST(StatusOr, TestValueConst) {
- const int kI = 4;
- const absl::StatusOr<int> thing(kI);
- EXPECT_EQ(kI, *thing);
-}
-
-TEST(StatusOr, TestPointerDefaultCtor) {
- absl::StatusOr<int*> thing;
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
-}
-
-TEST(StatusOr, TestPointerStatusCtor) {
- absl::StatusOr<int*> thing(absl::CancelledError());
- EXPECT_FALSE(thing.ok());
- EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestPointerValueCtor) {
- const int kI = 4;
-
- // Construction from a non-null pointer
- {
- absl::StatusOr<const int*> so(&kI);
- EXPECT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(&kI, *so);
- }
-
- // Construction from a null pointer constant
- {
- absl::StatusOr<const int*> so(nullptr);
- EXPECT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(nullptr, *so);
- }
-
- // Construction from a non-literal null pointer
- {
- const int* const p = nullptr;
-
- absl::StatusOr<const int*> so(p);
- EXPECT_TRUE(so.ok());
- EXPECT_OK(so.status());
- EXPECT_EQ(nullptr, *so);
- }
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusOk) {
- const int kI = 0;
- absl::StatusOr<const int*> original(&kI);
- absl::StatusOr<const int*> copy(original);
- EXPECT_OK(copy.status());
- EXPECT_EQ(*original, *copy);
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
- absl::StatusOr<int*> original(absl::CancelledError());
- absl::StatusOr<int*> copy(original);
- EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
- Derived derived;
- absl::StatusOr<Derived*> original(&derived);
- absl::StatusOr<Base2*> copy(original);
- EXPECT_OK(copy.status());
- EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
- absl::StatusOr<Derived*> original(absl::CancelledError());
- absl::StatusOr<Base2*> copy(original);
- EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusOk) {
- const int kI = 0;
- absl::StatusOr<const int*> source(&kI);
- absl::StatusOr<const int*> target;
- target = source;
- EXPECT_OK(target.status());
- EXPECT_EQ(*source, *target);
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
- absl::StatusOr<int*> source(absl::CancelledError());
- absl::StatusOr<int*> target;
- target = source;
- EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
- Derived derived;
- absl::StatusOr<Derived*> source(&derived);
- absl::StatusOr<Base2*> target;
- target = source;
- EXPECT_OK(target.status());
- EXPECT_EQ(static_cast<const Base2*>(*source), *target);
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
- absl::StatusOr<Derived*> source(absl::CancelledError());
- absl::StatusOr<Base2*> target;
- target = source;
- EXPECT_EQ(target.status(), source.status());
-}
-
-TEST(StatusOr, TestPointerStatus) {
- const int kI = 0;
- absl::StatusOr<const int*> good(&kI);
- EXPECT_TRUE(good.ok());
- absl::StatusOr<const int*> bad(absl::CancelledError());
- EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
-}
-
-TEST(StatusOr, TestPointerValue) {
- const int kI = 0;
- absl::StatusOr<const int*> thing(&kI);
- EXPECT_EQ(&kI, *thing);
-}
-
-TEST(StatusOr, TestPointerValueConst) {
- const int kI = 0;
- const absl::StatusOr<const int*> thing(&kI);
- EXPECT_EQ(&kI, *thing);
-}
-
-TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {
- using EvilType = std::vector<std::unique_ptr<int>>;
- static_assert(std::is_copy_constructible<EvilType>::value, "");
- std::vector<::absl::StatusOr<EvilType>> v(5);
- v.reserve(v.capacity() + 10);
- v.resize(v.capacity() + 10);
-}
-
-TEST(StatusOr, ConstPayload) {
- // A reduced version of a problematic type found in the wild. All of the
- // operations below should compile.
- absl::StatusOr<const int> a;
-
- // Copy-construction
- absl::StatusOr<const int> b(a);
-
- // Copy-assignment
- EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);
-
- // Move-construction
- absl::StatusOr<const int> c(std::move(a));
-
- // Move-assignment
- EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);
-}
-
-TEST(StatusOr, MapToStatusOrUniquePtr) {
- // A reduced version of a problematic type found in the wild. All of the
- // operations below should compile.
- using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;
-
- MapType a;
-
- // Move-construction
- MapType b(std::move(a));
-
- // Move-assignment
- a = std::move(b);
-}
-
-TEST(StatusOr, ValueOrOk) {
- const absl::StatusOr<int> status_or = 0;
- EXPECT_EQ(status_or.value_or(-1), 0);
-}
-
-TEST(StatusOr, ValueOrDefault) {
- const absl::StatusOr<int> status_or = absl::CancelledError();
- EXPECT_EQ(status_or.value_or(-1), -1);
-}
-
-TEST(StatusOr, MoveOnlyValueOrOk) {
- EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
- .value_or(absl::make_unique<int>(-1)),
- Pointee(0));
-}
-
-TEST(StatusOr, MoveOnlyValueOrDefault) {
- EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())
- .value_or(absl::make_unique<int>(-1)),
- Pointee(-1));
-}
-
-static absl::StatusOr<int> MakeStatus() { return 100; }
-
-TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }
-
-TEST(StatusOr, EqualityOperator) {
- constexpr int kNumCases = 4;
- std::array<absl::StatusOr<int>, kNumCases> group1 = {
- absl::StatusOr<int>(1), absl::StatusOr<int>(2),
- absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
- absl::StatusOr<int>(absl::InternalError("msg"))};
- std::array<absl::StatusOr<int>, kNumCases> group2 = {
- absl::StatusOr<int>(1), absl::StatusOr<int>(2),
- absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
- absl::StatusOr<int>(absl::InternalError("msg"))};
- for (int i = 0; i < kNumCases; ++i) {
- for (int j = 0; j < kNumCases; ++j) {
- if (i == j) {
- EXPECT_TRUE(group1[i] == group2[j]);
- EXPECT_FALSE(group1[i] != group2[j]);
- } else {
- EXPECT_FALSE(group1[i] == group2[j]);
- EXPECT_TRUE(group1[i] != group2[j]);
- }
- }
- }
-}
-
-struct MyType {
- bool operator==(const MyType&) const { return true; }
-};
-
-enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
-
-// This class has conversion operator to `StatusOr<T>` based on value of
-// `conv_traits`.
-template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
-struct StatusOrConversionBase {};
-
-template <typename T>
-struct StatusOrConversionBase<T, ConvTraits::kImplicit> {
- operator absl::StatusOr<T>() const& { // NOLINT
- return absl::InvalidArgumentError("conversion to absl::StatusOr");
- }
- operator absl::StatusOr<T>() && { // NOLINT
- return absl::InvalidArgumentError("conversion to absl::StatusOr");
- }
-};
-
-template <typename T>
-struct StatusOrConversionBase<T, ConvTraits::kExplicit> {
- explicit operator absl::StatusOr<T>() const& {
- return absl::InvalidArgumentError("conversion to absl::StatusOr");
- }
- explicit operator absl::StatusOr<T>() && {
- return absl::InvalidArgumentError("conversion to absl::StatusOr");
- }
-};
-
-// This class has conversion operator to `T` based on the value of
-// `conv_traits`.
-template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
-struct ConversionBase {};
-
-template <typename T>
-struct ConversionBase<T, ConvTraits::kImplicit> {
- operator T() const& { return t; } // NOLINT
- operator T() && { return std::move(t); } // NOLINT
- T t;
-};
-
-template <typename T>
-struct ConversionBase<T, ConvTraits::kExplicit> {
- explicit operator T() const& { return t; }
- explicit operator T() && { return std::move(t); }
- T t;
-};
-
-// This class has conversion operator to `absl::Status` based on the value of
-// `conv_traits`.
-template <ConvTraits conv_traits = ConvTraits::kNone>
-struct StatusConversionBase {};
-
-template <>
-struct StatusConversionBase<ConvTraits::kImplicit> {
- operator absl::Status() const& { // NOLINT
- return absl::InternalError("conversion to Status");
- }
- operator absl::Status() && { // NOLINT
- return absl::InternalError("conversion to Status");
- }
-};
-
-template <>
-struct StatusConversionBase<ConvTraits::kExplicit> {
- explicit operator absl::Status() const& { // NOLINT
- return absl::InternalError("conversion to Status");
- }
- explicit operator absl::Status() && { // NOLINT
- return absl::InternalError("conversion to Status");
- }
-};
-
-static constexpr int kConvToStatus = 1;
-static constexpr int kConvToStatusOr = 2;
-static constexpr int kConvToT = 4;
-static constexpr int kConvExplicit = 8;
-
-constexpr ConvTraits GetConvTraits(int bit, int config) {
- return (config & bit) == 0
- ? ConvTraits::kNone
- : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
- : ConvTraits::kExplicit);
-}
-
-// This class conditionally has conversion operator to `absl::Status`, `T`,
-// `StatusOr<T>`, based on values of the template parameters.
-template <typename T, int config>
-struct CustomType
- : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,
- ConversionBase<T, GetConvTraits(kConvToT, config)>,
- StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
-
-struct ConvertibleToAnyStatusOr {
- template <typename T>
- operator absl::StatusOr<T>() const { // NOLINT
- return absl::InvalidArgumentError("Conversion to absl::StatusOr");
- }
-};
-
-// Test the rank of overload resolution for `StatusOr<T>` constructor and
-// assignment, from highest to lowest:
-// 1. T/Status
-// 2. U that has conversion operator to absl::StatusOr<T>
-// 3. U that is convertible to Status
-// 4. U that is convertible to T
-TEST(StatusOr, ConstructionFromT) {
- // Construct absl::StatusOr<T> from T when T is convertible to
- // absl::StatusOr<T>
- {
- ConvertibleToAnyStatusOr v;
- absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);
- EXPECT_TRUE(statusor.ok());
- }
- {
- ConvertibleToAnyStatusOr v;
- absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;
- EXPECT_TRUE(statusor.ok());
- }
- // Construct absl::StatusOr<T> from T when T is explicitly convertible to
- // Status
- {
- CustomType<MyType, kConvToStatus | kConvExplicit> v;
- absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(
- v);
- EXPECT_TRUE(statusor.ok());
- }
- {
- CustomType<MyType, kConvToStatus | kConvExplicit> v;
- absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =
- v;
- EXPECT_TRUE(statusor.ok());
- }
-}
-
-// Construct absl::StatusOr<T> from U when U is explicitly convertible to T
-TEST(StatusOr, ConstructionFromTypeConvertibleToT) {
- {
- CustomType<MyType, kConvToT | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_TRUE(statusor.ok());
- }
- {
- CustomType<MyType, kConvToT> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_TRUE(statusor.ok());
- }
-}
-
-// Construct absl::StatusOr<T> from U when U has explicit conversion operator to
-// absl::StatusOr<T>
-TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {
- {
- CustomType<MyType, kConvToStatusOr | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType,
- kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>
- v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToStatusOr> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToT | kConvToStatusOr> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
-}
-
-TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {
- // Construction fails because conversion to `Status` is explicit.
- {
- CustomType<MyType, kConvToStatus | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
- {
- CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
- absl::StatusOr<MyType> statusor(v);
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
- {
- CustomType<MyType, kConvToStatus> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
- {
- CustomType<MyType, kConvToT | kConvToStatus> v;
- absl::StatusOr<MyType> statusor = v;
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
-}
-
-TEST(StatusOr, AssignmentFromT) {
- // Assign to absl::StatusOr<T> from T when T is convertible to
- // absl::StatusOr<T>
- {
- ConvertibleToAnyStatusOr v;
- absl::StatusOr<ConvertibleToAnyStatusOr> statusor;
- statusor = v;
- EXPECT_TRUE(statusor.ok());
- }
- // Assign to absl::StatusOr<T> from T when T is convertible to Status
- {
- CustomType<MyType, kConvToStatus> v;
- absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;
- statusor = v;
- EXPECT_TRUE(statusor.ok());
- }
-}
-
-TEST(StatusOr, AssignmentFromTypeConvertibleToT) {
- // Assign to absl::StatusOr<T> from U when U is convertible to T
- {
- CustomType<MyType, kConvToT> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_TRUE(statusor.ok());
- }
-}
-
-TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {
- // Assign to absl::StatusOr<T> from U when U has conversion operator to
- // absl::StatusOr<T>
- {
- CustomType<MyType, kConvToStatusOr> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToT | kConvToStatusOr> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
- {
- CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
- }
-}
-
-TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {
- // Assign to absl::StatusOr<T> from U when U is convertible to Status
- {
- CustomType<MyType, kConvToStatus> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
- {
- CustomType<MyType, kConvToT | kConvToStatus> v;
- absl::StatusOr<MyType> statusor;
- statusor = v;
- EXPECT_FALSE(statusor.ok());
- EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
- }
-}
-
-} // namespace