diff options
author | Dino Radakovic <dinor@google.com> | 2023-05-05 13:16:06 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-05-05 13:17:17 -0700 |
commit | 419b54d4870e31ae2442b7f453c7b8d5b8c08026 (patch) | |
tree | 1193cbd2a4883a4f45711e12b801f9ff097df5a5 | |
parent | f39f340c589354db8ab2f07894894f23c9ea3ae6 (diff) |
Make `absl::StatusOr::AssignStatus` public. Recommend against using it outside of generic programming (attempt #2 after internal fix)
PiperOrigin-RevId: 529796927
Change-Id: I755b7d907f96f4a05d01620503bf0862ce35e847
-rw-r--r-- | absl/status/statusor.h | 15 | ||||
-rw-r--r-- | absl/status/statusor_test.cc | 33 |
2 files changed, 48 insertions, 0 deletions
diff --git a/absl/status/statusor.h b/absl/status/statusor.h index beedd795..f1932238 100644 --- a/absl/status/statusor.h +++ b/absl/status/statusor.h @@ -612,6 +612,21 @@ class StatusOr : private internal_statusor::StatusOrData<T>, return this->data_; } + // StatusOr<T>::AssignStatus() + // + // Sets the status of `absl::StatusOr<T>` to the given non-ok status value. + // + // NOTE: We recommend using the constructor and `operator=` where possible. + // This method is intended for use in generic programming, to enable setting + // the status of a `StatusOr<T>` when `T` may be `Status`. In that case, the + // constructor and `operator=` would assign into the inner value of type + // `Status`, rather than status of the `StatusOr` (b/280392796). + // + // 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. + using internal_statusor::StatusOrData<T>::AssignStatus; + private: using internal_statusor::StatusOrData<T>::Assign; template <typename U> diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc index 29021543..e65f5d27 100644 --- a/absl/status/statusor_test.cc +++ b/absl/status/statusor_test.cc @@ -1844,4 +1844,37 @@ TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) { } } +TEST(StatusOr, StatusAssignmentFromStatusError) { + absl::StatusOr<absl::Status> statusor; + statusor.AssignStatus(absl::CancelledError()); + + EXPECT_FALSE(statusor.ok()); + EXPECT_EQ(statusor.status(), absl::CancelledError()); +} + +#if GTEST_HAS_DEATH_TEST +TEST(StatusOr, StatusAssignmentFromStatusOk) { + EXPECT_DEBUG_DEATH( + { + absl::StatusOr<absl::Status> statusor; + // This will DCHECK. + statusor.AssignStatus(absl::OkStatus()); + // In optimized mode, we are actually going to get error::INTERNAL for + // status here, rather than crashing, so check that. + EXPECT_FALSE(statusor.ok()); + EXPECT_EQ(statusor.status().code(), absl::StatusCode::kInternal); + }, + "An OK status is not a valid constructor argument to StatusOr<T>"); +} +#endif + +TEST(StatusOr, StatusAssignmentFromTypeConvertibleToStatus) { + CustomType<MyType, kConvToStatus> v; + absl::StatusOr<MyType> statusor; + statusor.AssignStatus(v); + + EXPECT_FALSE(statusor.ok()); + EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v)); +} + } // namespace |