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]

Reply via email to