igor-anferov commented on code in PR #44477:
URL: https://github.com/apache/arrow/pull/44477#discussion_r1809574569
##########
cpp/src/arrow/result.h:
##########
@@ -294,7 +294,13 @@ class [[nodiscard]] Result : public
util::EqualityComparable<Result<T>> {
///
/// \return The stored non-OK status object, or an OK status if this object
/// has a value.
- constexpr const Status& status() const { return status_; }
+ constexpr const Status& status() const& { return status_; }
+
+ /// Gets the stored status object, or an OK status if a `T` value is stored.
+ ///
+ /// \return The stored non-OK status object, or an OK status if this object
+ /// has a value.
+ Status status() && { return status_; }
Review Comment:
The issue with this is that std::move(status_) will leave status_ in an OK
state (since the internal state_ pointer will be NULL afterward). As a result,
the Result destructor will attempt to call a destructor on the storage_ field,
leading to undefined behavior because storage_ is uninitialized when the
original Result was constructed in an error state. One possible solution
(assuming we need to minimize the size of Result without simply putting status_
and storage_ in a variant) is for the move constructor of Status to preserve
the binary OK/error state of the moved-out object. This could be achieved
without changing the size of Status by using pointer tagging for its state_
field. There is a
[proposal](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3125r1.html)
for this, which will likely make it into C++26, but until then, there’s no
truly safe way to do this while complying with the current C++ standard…
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]