summaryrefslogtreecommitdiff
path: root/absl/status
diff options
context:
space:
mode:
authorGravatar Dino Radakovic <dinor@google.com>2023-05-05 13:16:06 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2023-05-05 13:17:17 -0700
commit419b54d4870e31ae2442b7f453c7b8d5b8c08026 (patch)
tree1193cbd2a4883a4f45711e12b801f9ff097df5a5 /absl/status
parentf39f340c589354db8ab2f07894894f23c9ea3ae6 (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
Diffstat (limited to 'absl/status')
-rw-r--r--absl/status/statusor.h15
-rw-r--r--absl/status/statusor_test.cc33
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