[fit] Add functions for creating promises that complete immediately.

Added fit::make_result_promise(), fit::make_ok_promise(),
and fit::make_error_promise().
Adopted the new helpers in various places that benefit from it.

Test: fit-test
Change-Id: Id7519f2c25df8d2caff276286710051bad6ef9f1
diff --git a/garnet/public/lib/inspect/discovery/object_source.cc b/garnet/public/lib/inspect/discovery/object_source.cc
index 2d3a3ed..e14ec0a 100644
--- a/garnet/public/lib/inspect/discovery/object_source.cc
+++ b/garnet/public/lib/inspect/discovery/object_source.cc
@@ -318,8 +318,7 @@
     if (status != ZX_OK || !file_ptr.is_bound()) {
       FXL_LOG(WARNING) << "Failed to fdio_open and bind "
                        << location.AbsoluteFilePath() << " " << status;
-      return fit::make_promise(
-          []() -> fit::result<ObjectSource> { return fit::error(); });
+      return fit::make_result_promise<ObjectSource>(fit::error());
     }
     return ObjectSource::Make(std::move(location), std::move(file_ptr), depth);
   } else {
@@ -328,8 +327,7 @@
   }
 
   FXL_LOG(ERROR) << "Failed to open " << location.AbsoluteFilePath();
-  return fit::make_promise(
-      []() -> fit::result<ObjectSource> { return fit::error(); });
+  return fit::make_result_promise<ObjectSource>(fit::error());
 }
 
 // Consult the file system to find out how to open an inspect endpoint at the
diff --git a/garnet/tests/zircon/libdriver-integration-test/integration-test.h b/garnet/tests/zircon/libdriver-integration-test/integration-test.h
index 68a6463..08b61b0 100644
--- a/garnet/tests/zircon/libdriver-integration-test/integration-test.h
+++ b/garnet/tests/zircon/libdriver-integration-test/integration-test.h
@@ -26,7 +26,7 @@
           assertion; \
       }(); \
       if (testing::Test::HasFatalFailure()) { \
-          return fit::make_promise([]() { return fit::error(std::string("Assertion failure")); }); \
+          return fit::make_error_promise(std::string("Assertion failure")); \
       } \
     } while (0)
 
diff --git a/peridot/bin/sessionmgr/story/model/ledger_story_model_storage.cc b/peridot/bin/sessionmgr/story/model/ledger_story_model_storage.cc
index a08cf8c..20864ce 100644
--- a/peridot/bin/sessionmgr/story/model/ledger_story_model_storage.cc
+++ b/peridot/bin/sessionmgr/story/model/ledger_story_model_storage.cc
@@ -263,7 +263,7 @@
                                  fuchsia::ledger::PageSnapshot* snapshot,
                                  std::vector<StoryModelMutation> commands) {
   // There is no shared state yet.
-  return fit::make_promise([] { return fit::ok(); });
+  return fit::make_ok_promise();
 }
 }  // namespace
 
@@ -313,7 +313,7 @@
   // The returned promise will block until all pending mutation opertaions have
   // resolved. These pending operations are also wrapped with |sequencer_| (in
   // Execute()), which applies this sequential behavior to promises it wraps.
-  return fit::make_promise([] { return fit::ok(); }).wrap_with(sequencer_);
+  return fit::make_ok_promise().wrap_with(sequencer_);
 }
 
 fit::promise<> LedgerStoryModelStorage::Execute(
diff --git a/peridot/bin/sessionmgr/story/model/noop_story_model_storage.cc b/peridot/bin/sessionmgr/story/model/noop_story_model_storage.cc
index 0f143ad..b77e5f2 100644
--- a/peridot/bin/sessionmgr/story/model/noop_story_model_storage.cc
+++ b/peridot/bin/sessionmgr/story/model/noop_story_model_storage.cc
@@ -11,13 +11,9 @@
 NoopStoryModelStorage::NoopStoryModelStorage() = default;
 NoopStoryModelStorage::~NoopStoryModelStorage() = default;
 
-fit::promise<> NoopStoryModelStorage::Load() {
-  return fit::make_promise([] { return fit::ok(); });
-}
+fit::promise<> NoopStoryModelStorage::Load() { return fit::make_ok_promise(); }
 
-fit::promise<> NoopStoryModelStorage::Flush() {
-  return fit::make_promise([] { return fit::ok(); });
-}
+fit::promise<> NoopStoryModelStorage::Flush() { return fit::make_ok_promise(); }
 
 fit::promise<> NoopStoryModelStorage::Execute(
     std::vector<fuchsia::modular::storymodel::StoryModelMutation> commands) {
diff --git a/peridot/bin/sessionmgr/story/model/story_model_owner_unittest.cc b/peridot/bin/sessionmgr/story/model/story_model_owner_unittest.cc
index bd33ab2..0267c24 100644
--- a/peridot/bin/sessionmgr/story/model/story_model_owner_unittest.cc
+++ b/peridot/bin/sessionmgr/story/model/story_model_owner_unittest.cc
@@ -30,13 +30,9 @@
   };
   std::vector<ExecuteCall> calls;
 
-  fit::promise<> Load() override {
-    return fit::make_promise([] { return fit::ok(); });
-  }
+  fit::promise<> Load() override { return fit::make_ok_promise(); }
 
-  fit::promise<> Flush() override {
-    return fit::make_promise([] { return fit::ok(); });
-  }
+  fit::promise<> Flush() override { return fit::make_ok_promise(); }
 
   fit::promise<> Execute(std::vector<StoryModelMutation> commands) override {
     fit::bridge<> bridge;
diff --git a/src/connectivity/network/testing/netemul/runner/sandbox.cc b/src/connectivity/network/testing/netemul/runner/sandbox.cc
index 5bdbcfa0..c126246 100644
--- a/src/connectivity/network/testing/netemul/runner/sandbox.cc
+++ b/src/connectivity/network/testing/netemul/runner/sandbox.cc
@@ -369,7 +369,7 @@
     const config::Environment* config,
     ConfiguringEnvironmentLauncher launcher) {
   return fit::make_promise([this, config, launcher = std::move(launcher)] {
-    auto prom = fit::make_promise([] { return fit::ok(); }).box();
+    auto prom = fit::make_ok_promise().box();
     for (const auto& setup : config->setup()) {
       prom = prom.and_then([this, setup = &setup, launcher]() {
                    return LaunchSetup(
diff --git a/zircon/docs/fit_promise_guide.md b/zircon/docs/fit_promise_guide.md
index b714a48..4ef9dde 100644
--- a/zircon/docs/fit_promise_guide.md
+++ b/zircon/docs/fit_promise_guide.md
@@ -303,7 +303,7 @@
   if (condition) {
     return MakeComplexPromise();
   }
-  return fit::make_promise([] { return fit::ok(); });
+  return fit::make_ok_promise(42);
 });
 ```
 
diff --git a/zircon/system/ulib/fit/include/lib/fit/promise.h b/zircon/system/ulib/fit/include/lib/fit/promise.h
index 8ec7a1f..b0059b3 100644
--- a/zircon/system/ulib/fit/include/lib/fit/promise.h
+++ b/zircon/system/ulib/fit/include/lib/fit/promise.h
@@ -26,6 +26,9 @@
 // a variety of combinators such as |then()|.
 //
 // Use |fit::make_promise()| to create a promise.
+// Use |fit::make_ok_promise()| to create a promise that immediately returns a value.
+// Use |fit::make_error_promise()| to create a promise that immediately returns an error.
+// Use |fit::make_result_promise()| to create a promise that immediately returns a result.
 // Use |fit::future| to more conveniently hold a promise or its result.
 // Use |fit::pending_task| to wrap a promise as a pending task for execution.
 // Use |fit::executor| to execute a pending task.
@@ -857,6 +860,79 @@
             std::move(handler)));
 }
 
+// Returns an unboxed promise that immediately returns the specified result when invoked.
+//
+// This function is especially useful for returning promises from functions
+// that have multiple branches some of which complete synchronously.
+//
+// |result| is the result for the promise to return.
+//
+// See documentation of |fit::promise| for more information.
+template <typename V = void, typename E = void>
+inline promise_impl<::fit::internal::result_continuation<V, E>>
+make_result_promise(fit::result<V, E> result) {
+    return make_promise_with_continuation(
+        ::fit::internal::result_continuation<V, E>(std::move(result)));
+}
+template <typename V = void, typename E = void>
+inline promise_impl<::fit::internal::result_continuation<V, E>>
+make_result_promise(fit::ok_result<V> result) {
+    return make_promise_with_continuation(
+        ::fit::internal::result_continuation<V, E>(std::move(result)));
+}
+template <typename V = void, typename E = void>
+inline promise_impl<::fit::internal::result_continuation<V, E>>
+make_result_promise(fit::error_result<E> result) {
+    return make_promise_with_continuation(
+        ::fit::internal::result_continuation<V, E>(std::move(result)));
+}
+template <typename V = void, typename E = void>
+inline promise_impl<::fit::internal::result_continuation<V, E>>
+make_result_promise(fit::pending_result result) {
+    return make_promise_with_continuation(
+        ::fit::internal::result_continuation<V, E>(std::move(result)));
+}
+
+// Returns an unboxed promise that immediately returns the specified value when invoked.
+//
+// This function is especially useful for returning promises from functions
+// that have multiple branches some of which complete synchronously.
+//
+// |value| is the value for the promise to return.
+//
+// See documentation of |fit::promise| for more information.
+template <typename V>
+inline promise_impl<::fit::internal::result_continuation<V, void>>
+make_ok_promise(V value) {
+    return make_result_promise(fit::ok(std::move(value)));
+}
+
+// Overload of |make_ok_promise()| used when the value type is void.
+inline promise_impl<::fit::internal::result_continuation<void, void>>
+make_ok_promise() {
+    return make_result_promise(fit::ok());
+}
+
+// Returns an unboxed promise that immediately returns the specified error when invoked.
+//
+// This function is especially useful for returning promises from functions
+// that have multiple branches some of which complete synchronously.
+//
+// |error| is the error for the promise to return.
+//
+// See documentation of |fit::promise| for more information.
+template <typename E>
+inline promise_impl<::fit::internal::result_continuation<void, E>>
+make_error_promise(E error) {
+    return make_result_promise(fit::error(std::move(error)));
+}
+
+// Overload of |make_error_promise()| used when the error type is void.
+inline promise_impl<::fit::internal::result_continuation<void, void>>
+make_error_promise() {
+    return make_result_promise(fit::error());
+}
+
 // Jointly evaluates zero or more promises.
 // Returns a promise that produces a std::tuple<> containing the result
 // of each promise once they all complete.
diff --git a/zircon/system/ulib/fit/include/lib/fit/promise_internal.h b/zircon/system/ulib/fit/include/lib/fit/promise_internal.h
index 9a162db..489d5a0 100644
--- a/zircon/system/ulib/fit/include/lib/fit/promise_internal.h
+++ b/zircon/system/ulib/fit/include/lib/fit/promise_internal.h
@@ -545,6 +545,21 @@
 template <typename PromiseHandler>
 using promise_continuation = context_handler_invoker<PromiseHandler>;
 
+// The continuation produced by |make_result_promise()|.
+template <typename V, typename E>
+class result_continuation final {
+public:
+    explicit result_continuation(::fit::result<V, E> result)
+        : result_(std::move(result)) {}
+
+    ::fit::result<V, E> operator()(::fit::context& context) {
+        return std::move(result_);
+    }
+
+private:
+    ::fit::result<V, E> result_;
+};
+
 // Returns true if all arguments are true or if there are none.
 inline bool all_true() {
     return true;
diff --git a/zircon/system/utest/fit/promise_tests.cpp b/zircon/system/utest/fit/promise_tests.cpp
index e6f71ce..6468ab0 100644
--- a/zircon/system/utest/fit/promise_tests.cpp
+++ b/zircon/system/utest/fit/promise_tests.cpp
@@ -399,7 +399,137 @@
     END_TEST;
 }
 
-auto make_ok_promise(int value) {
+bool make_result_promise() {
+    BEGIN_TEST;
+
+    fake_context fake_context;
+
+    // Argument type: fit::result<int, char>
+    {
+        auto p = fit::make_result_promise(fit::result<int, char>(fit::ok(42)));
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<int, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::ok, result.state());
+        EXPECT_EQ(42, result.value());
+    }
+
+    // Argument type: fit::ok_result<int> with inferred types
+    {
+        auto p = fit::make_result_promise(fit::ok(42));
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
+        fit::result<int, void> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::ok, result.state());
+        EXPECT_EQ(42, result.value());
+    }
+
+    // Argument type: fit::ok_result<int> with explicit types
+    {
+        auto p = fit::make_result_promise<int, char>(fit::ok(42));
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<int, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::ok, result.state());
+        EXPECT_EQ(42, result.value());
+    }
+
+    // Argument type: fit::error_result<char> with inferred types
+    {
+        auto p = fit::make_result_promise(fit::error('x'));
+        static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<void, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::error, result.state());
+        EXPECT_EQ('x', result.error());
+    }
+
+    // Argument type: fit::error_result<char> with explicit types
+    {
+        auto p = fit::make_result_promise<int, char>(fit::error('x'));
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<int, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::error, result.state());
+        EXPECT_EQ('x', result.error());
+    }
+
+    // Argument type: fit::pending_result with inferred types
+    {
+        auto p = fit::make_result_promise(fit::pending());
+        static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
+        fit::result<void, void> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::pending, result.state());
+    }
+
+    // Argument type: fit::pending_result with explicit types
+    {
+        auto p = fit::make_result_promise<int, char>(fit::pending());
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<int, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::pending, result.state());
+    }
+
+    END_TEST;
+}
+
+bool make_ok_promise() {
+    BEGIN_TEST;
+
+    fake_context fake_context;
+
+    // Argument type: int
+    {
+        auto p = fit::make_ok_promise(42);
+        static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
+        fit::result<int, void> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::ok, result.state());
+        EXPECT_EQ(42, result.value());
+    }
+
+    // Argument type: none (void)
+    {
+        auto p = fit::make_ok_promise();
+        static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
+        fit::result<void, void> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::ok, result.state());
+    }
+
+    END_TEST;
+}
+
+bool make_error_promise() {
+    BEGIN_TEST;
+
+    fake_context fake_context;
+
+    // Argument type: int
+    {
+        auto p = fit::make_error_promise('x');
+        static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
+        fit::result<void, char> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::error, result.state());
+        EXPECT_EQ('x', result.error());
+    }
+
+    // Argument type: none (void)
+    {
+        auto p = fit::make_error_promise();
+        static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
+        static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
+        fit::result<void, void> result = p(fake_context);
+        EXPECT_EQ(fit::result_state::error, result.state());
+    }
+
+    END_TEST;
+}
+
+auto make_checked_ok_promise(int value) {
     return fit::make_promise([value, count = 0]() mutable -> fit::result<int, char> {
         ASSERT_CRITICAL(count == 0);
         ++count;
@@ -416,7 +546,7 @@
     });
 }
 
-auto make_error_promise(char error) {
+auto make_checked_error_promise(char error) {
     return fit::make_promise([error, count = 0]() mutable -> fit::result<int, char> {
         ASSERT_CRITICAL(count == 0);
         ++count;
@@ -512,7 +642,7 @@
     {
         uint64_t run_count = 0;
         auto p =
-            make_ok_promise(42)
+            make_checked_ok_promise(42)
                 .then([&](fit::result<int, char>& result)
                           -> fit::result<int, char> {
                     run_count++;
@@ -608,7 +738,7 @@
     {
         uint64_t run_count = 0;
         auto p =
-            make_ok_promise(42)
+            make_checked_ok_promise(42)
                 .and_then([&](int& value)
                               -> fit::result<int, char> {
                     run_count++;
@@ -704,7 +834,7 @@
     {
         uint64_t run_count = 0;
         auto p =
-            make_error_promise('a')
+            make_checked_error_promise('a')
                 .or_else([&](char& error)
                              -> fit::result<int, char> {
                     run_count++;
@@ -793,7 +923,7 @@
     {
         uint64_t run_count = 0;
         auto p =
-            make_ok_promise(42)
+            make_checked_ok_promise(42)
                 .inspect([&](fit::result<int, char>& result) {
                     ASSERT_CRITICAL(result.value() == 42);
                     run_count++;
@@ -922,8 +1052,8 @@
     fake_context fake_context;
 
     auto p = fit::join_promises(
-        make_ok_promise(42),
-        make_error_promise('x').or_else([](const char& error) {
+        make_checked_ok_promise(42),
+        make_checked_error_promise('x').or_else([](const char& error) {
             return fit::error('y');
         }),
         make_delayed_ok_promise(55));
@@ -981,8 +1111,8 @@
     fake_context fake_context;
 
     std::vector<fit::promise<int, char>> promises;
-    promises.push_back(make_ok_promise(42));
-    promises.push_back(make_error_promise('x').or_else([](const char& error) {
+    promises.push_back(make_checked_ok_promise(42));
+    promises.push_back(make_checked_error_promise('x').or_else([](const char& error) {
         return fit::error('y');
     }));
     promises.push_back(make_delayed_ok_promise(55));
@@ -1254,6 +1384,9 @@
 RUN_TEST(comparison_with_nullptr)
 RUN_TEST(make_promise)
 RUN_TEST(make_promise_with_continuation)
+RUN_TEST(make_result_promise)
+RUN_TEST(make_ok_promise)
+RUN_TEST(make_error_promise)
 RUN_TEST(then_combinator)
 RUN_TEST(and_then_combinator)
 RUN_TEST(or_else_combinator)