Commit 37d13ba2 authored by Lee Howes's avatar Lee Howes Committed by Facebook Github Bot

Remove void-callability from tryCallableResult to enforce clean separation.

Summary:
Makes it invalid to call SemiFuture::defer with a lambda that takes no arguments.

Fix to callsites in folly tests that checked this behaviour.

Reviewed By: yfeldblum

Differential Revision: D9511831

fbshipit-source-id: 11e600cea78887c653e3d0d0e1cd2091c4eb191e
parent fdfdc324
...@@ -107,10 +107,7 @@ struct callableResult { ...@@ -107,10 +107,7 @@ struct callableResult {
template <typename T, typename F> template <typename T, typename F>
struct tryCallableResult { struct tryCallableResult {
typedef typename std::conditional< typedef detail::argResult<true, F, Try<T>&&> Arg;
is_invocable<F>::value,
detail::argResult<false, F>,
detail::argResult<true, F, Try<T>&&>>::type Arg;
typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture; typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
typedef typename ReturnsFuture::Inner value_type; typedef typename ReturnsFuture::Inner value_type;
typedef Future<value_type> Return; typedef Future<value_type> Return;
......
...@@ -573,7 +573,7 @@ TEST(SemiFuture, SimpleDefer) { ...@@ -573,7 +573,7 @@ TEST(SemiFuture, SimpleDefer) {
std::atomic<int> innerResult{0}; std::atomic<int> innerResult{0};
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { innerResult = 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
p.setValue(); p.setValue();
// Run "F" here inline in the calling thread // Run "F" here inline in the calling thread
std::move(sf).get(); std::move(sf).get();
...@@ -584,7 +584,7 @@ TEST(SemiFuture, DeferWithDelayedSetValue) { ...@@ -584,7 +584,7 @@ TEST(SemiFuture, DeferWithDelayedSetValue) {
EventBase e2; EventBase e2;
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { return 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { return 17; });
// Start thread and have it blocking in the semifuture before we satisfy the // Start thread and have it blocking in the semifuture before we satisfy the
// promise // promise
...@@ -604,7 +604,7 @@ TEST(SemiFuture, DeferWithViaAndDelayedSetValue) { ...@@ -604,7 +604,7 @@ TEST(SemiFuture, DeferWithViaAndDelayedSetValue) {
EventBase e2; EventBase e2;
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { return 17; }).via(&e2); auto sf = std::move(f).semi().defer([&](auto&&) { return 17; }).via(&e2);
// Start thread and have it blocking in the semifuture before we satisfy the // Start thread and have it blocking in the semifuture before we satisfy the
// promise. // promise.
auto resultF = auto resultF =
...@@ -625,7 +625,7 @@ TEST(SemiFuture, DeferWithGetTimedGet) { ...@@ -625,7 +625,7 @@ TEST(SemiFuture, DeferWithGetTimedGet) {
std::atomic<int> innerResult{0}; std::atomic<int> innerResult{0};
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { innerResult = 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
EXPECT_THROW( EXPECT_THROW(
std::move(sf).get(std::chrono::milliseconds(100)), FutureTimeout); std::move(sf).get(std::chrono::milliseconds(100)), FutureTimeout);
ASSERT_EQ(innerResult, 0); ASSERT_EQ(innerResult, 0);
...@@ -634,7 +634,7 @@ TEST(SemiFuture, DeferWithGetTimedGet) { ...@@ -634,7 +634,7 @@ TEST(SemiFuture, DeferWithGetTimedGet) {
TEST(SemiFuture, DeferWithGetTimedWait) { TEST(SemiFuture, DeferWithGetTimedWait) {
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { return 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { return 17; });
ASSERT_FALSE(sf.isReady()); ASSERT_FALSE(sf.isReady());
sf.wait(std::chrono::milliseconds(100)); sf.wait(std::chrono::milliseconds(100));
ASSERT_FALSE(sf.isReady()); ASSERT_FALSE(sf.isReady());
...@@ -645,7 +645,7 @@ TEST(SemiFuture, DeferWithGetTimedWait) { ...@@ -645,7 +645,7 @@ TEST(SemiFuture, DeferWithGetTimedWait) {
TEST(SemiFuture, DeferWithGetMultipleTimedWait) { TEST(SemiFuture, DeferWithGetMultipleTimedWait) {
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { return 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { return 17; });
sf.wait(std::chrono::milliseconds(100)); sf.wait(std::chrono::milliseconds(100));
sf.wait(std::chrono::milliseconds(100)); sf.wait(std::chrono::milliseconds(100));
ASSERT_FALSE(sf.isReady()); ASSERT_FALSE(sf.isReady());
...@@ -659,7 +659,7 @@ TEST(SemiFuture, DeferWithVia) { ...@@ -659,7 +659,7 @@ TEST(SemiFuture, DeferWithVia) {
EventBase e2; EventBase e2;
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { innerResult = 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
// Run "F" here inline in the calling thread // Run "F" here inline in the calling thread
auto tf = std::move(sf).via(&e2); auto tf = std::move(sf).via(&e2);
p.setValue(); p.setValue();
...@@ -673,7 +673,7 @@ TEST(SemiFuture, ChainingDefertoThen) { ...@@ -673,7 +673,7 @@ TEST(SemiFuture, ChainingDefertoThen) {
EventBase e2; EventBase e2;
Promise<folly::Unit> p; Promise<folly::Unit> p;
auto f = p.getSemiFuture().toUnsafeFuture(); auto f = p.getSemiFuture().toUnsafeFuture();
auto sf = std::move(f).semi().defer([&]() { innerResult = 17; }); auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
// Run "F" here inline in a task running on the eventbase // Run "F" here inline in a task running on the eventbase
auto tf = std::move(sf).via(&e2).then([&]() { result = 42; }); auto tf = std::move(sf).via(&e2).then([&]() { result = 42; });
p.setValue(); p.setValue();
...@@ -742,7 +742,7 @@ TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) { ...@@ -742,7 +742,7 @@ TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) {
} }
namespace { namespace {
[[noreturn]] void deferHelper() { throw eggs; } [[noreturn]] void deferHelper(folly::Try<folly::Unit>&&) { throw eggs; }
} // namespace } // namespace
TEST(SemiFuture, DeferWithinContinuation) { TEST(SemiFuture, DeferWithinContinuation) {
...@@ -786,7 +786,7 @@ TEST(SemiFuture, onError) { ...@@ -786,7 +786,7 @@ TEST(SemiFuture, onError) {
// By reference // By reference
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<eggs_t>([&](eggs_t const& /* e */) { flag(); }); .deferError<eggs_t>([&](eggs_t const& /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -803,7 +803,7 @@ TEST(SemiFuture, onError) { ...@@ -803,7 +803,7 @@ TEST(SemiFuture, onError) {
// By auto reference // By auto reference
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<eggs_t>([&](auto& /* e */) { flag(); }); .deferError<eggs_t>([&](auto& /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -812,7 +812,7 @@ TEST(SemiFuture, onError) { ...@@ -812,7 +812,7 @@ TEST(SemiFuture, onError) {
// By value // By value
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<eggs_t>([&](eggs_t /* e */) { flag(); }); .deferError<eggs_t>([&](eggs_t /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -821,7 +821,7 @@ TEST(SemiFuture, onError) { ...@@ -821,7 +821,7 @@ TEST(SemiFuture, onError) {
// auto value // auto value
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<eggs_t>([&](auto /* e */) { flag(); }); .deferError<eggs_t>([&](auto /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -831,7 +831,7 @@ TEST(SemiFuture, onError) { ...@@ -831,7 +831,7 @@ TEST(SemiFuture, onError) {
{ {
auto f = auto f =
makeSemiFuture() makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<std::exception>([&](auto const& /* e */) { flag(); }); .deferError<std::exception>([&](auto const& /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -840,7 +840,7 @@ TEST(SemiFuture, onError) { ...@@ -840,7 +840,7 @@ TEST(SemiFuture, onError) {
// Non-exceptions // Non-exceptions
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw - 1; }) .defer([](auto&&) { throw - 1; })
.deferError<int>([&](auto /* e */) { flag(); }); .deferError<int>([&](auto /* e */) { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -850,7 +850,7 @@ TEST(SemiFuture, onError) { ...@@ -850,7 +850,7 @@ TEST(SemiFuture, onError) {
{ {
auto f = auto f =
makeSemiFuture() makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<eggs_t>([&](auto const& /* e */) mutable { flag(); }); .deferError<eggs_t>([&](auto const& /* e */) mutable { flag(); });
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
...@@ -859,29 +859,31 @@ TEST(SemiFuture, onError) { ...@@ -859,29 +859,31 @@ TEST(SemiFuture, onError) {
// Function pointer // Function pointer
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([]() -> int { throw eggs; }) .defer([](auto &&) -> int { throw eggs; })
.deferError<eggs_t>(onErrorHelperEggs) .deferError<eggs_t>(onErrorHelperEggs)
.deferError(onErrorHelperGeneric); .deferError(onErrorHelperGeneric);
EXPECT_EQ(10, std::move(f).get()); EXPECT_EQ(10, std::move(f).get());
} }
{ {
auto f = makeSemiFuture() auto f =
.defer([]() -> int { throw std::runtime_error("test"); }) makeSemiFuture()
.deferError<eggs_t>(onErrorHelperEggs) .defer([](auto &&) -> int { throw std::runtime_error("test"); })
.deferError(onErrorHelperGeneric); .deferError<eggs_t>(onErrorHelperEggs)
.deferError(onErrorHelperGeneric);
EXPECT_EQ(20, std::move(f).get()); EXPECT_EQ(20, std::move(f).get());
} }
{ {
auto f = makeSemiFuture() auto f =
.defer([]() -> int { throw std::runtime_error("test"); }) makeSemiFuture()
.deferError<eggs_t>(onErrorHelperEggs); .defer([](auto &&) -> int { throw std::runtime_error("test"); })
.deferError<eggs_t>(onErrorHelperEggs);
EXPECT_THROW(std::move(f).get(), std::runtime_error); EXPECT_THROW(std::move(f).get(), std::runtime_error);
} }
// No throw // No throw
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { return 42; }) .defer([](auto&&) { return 42; })
.deferError<eggs_t>([&](auto& /* e */) { .deferError<eggs_t>([&](auto& /* e */) {
flag(); flag();
return -1; return -1;
...@@ -894,7 +896,7 @@ TEST(SemiFuture, onError) { ...@@ -894,7 +896,7 @@ TEST(SemiFuture, onError) {
// Catch different exception // Catch different exception
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError<std::runtime_error>( .deferError<std::runtime_error>(
[&](auto const& /* e */) { flag(); }); [&](auto const& /* e */) { flag(); });
EXPECT_THROW(std::move(f).get(), eggs_t); EXPECT_THROW(std::move(f).get(), eggs_t);
...@@ -904,7 +906,7 @@ TEST(SemiFuture, onError) { ...@@ -904,7 +906,7 @@ TEST(SemiFuture, onError) {
// Returned value propagates // Returned value propagates
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([]() -> int { throw eggs; }) .defer([](auto &&) -> int { throw eggs; })
.deferError<eggs_t>([&](auto const& /* e */) { return 42; }); .deferError<eggs_t>([&](auto const& /* e */) { return 42; });
EXPECT_EQ(42, std::move(f).get()); EXPECT_EQ(42, std::move(f).get());
} }
...@@ -912,7 +914,7 @@ TEST(SemiFuture, onError) { ...@@ -912,7 +914,7 @@ TEST(SemiFuture, onError) {
// Throw in callback // Throw in callback
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([]() -> int { throw eggs; }) .defer([](auto &&) -> int { throw eggs; })
.deferError<eggs_t>([&](auto const& e) -> int { throw e; }); .deferError<eggs_t>([&](auto const& e) -> int { throw e; });
EXPECT_THROW(std::move(f).get(), eggs_t); EXPECT_THROW(std::move(f).get(), eggs_t);
} }
...@@ -920,7 +922,7 @@ TEST(SemiFuture, onError) { ...@@ -920,7 +922,7 @@ TEST(SemiFuture, onError) {
// exception_wrapper, return T // exception_wrapper, return T
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([]() -> int { throw eggs; }) .defer([](auto &&) -> int { throw eggs; })
.deferError([&](exception_wrapper /* e */) { .deferError([&](exception_wrapper /* e */) {
flag(); flag();
return -1; return -1;
...@@ -932,7 +934,7 @@ TEST(SemiFuture, onError) { ...@@ -932,7 +934,7 @@ TEST(SemiFuture, onError) {
// exception_wrapper, return T but throw // exception_wrapper, return T but throw
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([]() -> int { throw eggs; }) .defer([](auto &&) -> int { throw eggs; })
.deferError([&](exception_wrapper /* e */) -> int { .deferError([&](exception_wrapper /* e */) -> int {
flag(); flag();
throw eggs; throw eggs;
...@@ -944,10 +946,8 @@ TEST(SemiFuture, onError) { ...@@ -944,10 +946,8 @@ TEST(SemiFuture, onError) {
// const exception_wrapper& // const exception_wrapper&
{ {
auto f = makeSemiFuture() auto f = makeSemiFuture()
.defer([] { throw eggs; }) .defer([](auto&&) { throw eggs; })
.deferError([&](const exception_wrapper& /* e */) { .deferError([&](const exception_wrapper& /* e */) { flag(); });
flag();
});
EXPECT_NO_THROW(std::move(f).get()); EXPECT_NO_THROW(std::move(f).get());
EXPECT_FLAG(); EXPECT_FLAG();
} }
......
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