Commit 587379a1 authored by Marshall Cline's avatar Marshall Cline Committed by Facebook Github Bot

rvalueification of Future::unwrap(...): 1/n

Summary:
This is part of "the great r-valuification of folly::Future":
* This is something we should do for safety in general.
* Several of folly::Future's methods are lvalue-qualified even though they act as though they are rvalue-qualified, that is, they provide a postcondition that says, in effect, callers should act as though the method invalidated its `this` object (regardless of whether that invalidation was actual or logical).
* This violates the C++ principle to "Express ideas directly in code" (see Core Guidelines), and generally makes it more confusing for callers as well as hiding the actual semantics from tools (linters, compilers, etc.).
* This dichotomy and confusion has manifested itself by some failures around D7840699 since lvalue-qualification hides that operation's move-out semantics - leads to some use of future operations that are really not correct, but are not obviously incorrect.
* The goal of rvalueification is to make sure methods that are logically rvalue-qualified are actually rvalue-qualified, which forces callsites to acknowledge that rvalueification, e.g., `std::move(f).unwrap(...)` instead of `f.unwrap(...)`. This syntactic change in the callsites forces callers to acknowledge the method's rvalue semantics.

Reviewed By: yfeldblum

Differential Revision: D9309748

fbshipit-source-id: eeda770f9e0d3462e1d4680e45d68c8355156b0c
parent 8146802f
......@@ -1017,7 +1017,7 @@ template <class T>
template <class F>
typename std::
enable_if<isFuture<F>::value, Future<typename isFuture<T>::Inner>>::type
Future<T>::unwrap() {
Future<T>::unwrap() && {
return std::move(*this).then(
[](Future<typename isFuture<T>::Inner> internal_future) {
return internal_future;
......
......@@ -1086,10 +1086,27 @@ class Future : private futures::detail::FutureBase<T> {
/// Unwraps the case of a Future<Future<T>> instance, and returns a simple
/// Future<T> instance.
///
/// Preconditions:
///
/// - `valid() == true` (else throws FutureInvalid)
///
/// Postconditions:
///
/// - Calling code should act as if `valid() == false`,
/// i.e., as if `*this` was moved into RESULT.
/// - `RESULT.valid() == true`
template <class F = T>
typename std::
enable_if<isFuture<F>::value, Future<typename isFuture<T>::Inner>>::type
unwrap();
unwrap() &&;
template <class F = T>
typename std::
enable_if<isFuture<F>::value, Future<typename isFuture<T>::Inner>>::type
unwrap() & {
return std::move(*this).unwrap();
}
/// Returns a Future which will call back on the other side of executor.
///
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment