Allow efficient construction of `absl::Status` from `std::string&&` using the convenience functions.

PiperOrigin-RevId: 966927834
Change-Id: Idc323be579b159786a66fedf7b44f9fdcd826f71
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
index 03b0663..81f6ce4 100644
--- a/absl/status/internal/status_internal.h
+++ b/absl/status/internal/status_internal.h
@@ -82,6 +82,9 @@
 
 using Payloads = absl::InlinedVector<Payload, 1>;
 
+template <typename T>
+using EnableIfString = std::enable_if_t<std::is_same_v<T, std::string>>;
+
 // Reference-counted representation of Status data.
 class StatusRep {
  public:
@@ -92,16 +95,13 @@
         message_(message_arg),
         payloads_(std::move(payloads_arg)) {}
 
-#ifndef SWIG
-  template <typename String,
-            typename = std::enable_if_t<std::is_same_v<String, std::string>>>
+  template <typename String, typename = EnableIfString<String>>
   StatusRep(absl::StatusCode code_arg, String&& message_arg,
             std::unique_ptr<status_internal::Payloads> payloads_arg)
       : ref_(int32_t{1}),
         code_(code_arg),
         message_(std::forward<String>(message_arg)),
         payloads_(std::move(payloads_arg)) {}
-#endif  // SWIG
 
   absl::StatusCode code() const { return code_; }
   const std::string& message() const { return message_; }
diff --git a/absl/status/status.cc b/absl/status/status.cc
index 155c5d8..555ae42 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -171,7 +171,7 @@
 namespace status_internal {
 // We use an int in the template parameter to shorten mangled names.
 template <int error_code>
-Status MakeErrorImpl(string_view message, SourceLocation loc) {
+Status MakeErrorStringViewImpl(string_view message, SourceLocation loc) {
   return Status(static_cast<StatusCode>(error_code), message, loc);
 }
 
@@ -179,23 +179,55 @@
 // If we add more error code, we need to add their values on this list.
 // Using ints here instead of static_cast<int>(StatusCode::kFoo) makes it easier
 // to see that the list is complete.
-template Status MakeErrorImpl<0>(string_view, SourceLocation);
-template Status MakeErrorImpl<1>(string_view, SourceLocation);
-template Status MakeErrorImpl<2>(string_view, SourceLocation);
-template Status MakeErrorImpl<3>(string_view, SourceLocation);
-template Status MakeErrorImpl<4>(string_view, SourceLocation);
-template Status MakeErrorImpl<5>(string_view, SourceLocation);
-template Status MakeErrorImpl<6>(string_view, SourceLocation);
-template Status MakeErrorImpl<7>(string_view, SourceLocation);
-template Status MakeErrorImpl<8>(string_view, SourceLocation);
-template Status MakeErrorImpl<9>(string_view, SourceLocation);
-template Status MakeErrorImpl<10>(string_view, SourceLocation);
-template Status MakeErrorImpl<11>(string_view, SourceLocation);
-template Status MakeErrorImpl<12>(string_view, SourceLocation);
-template Status MakeErrorImpl<13>(string_view, SourceLocation);
-template Status MakeErrorImpl<14>(string_view, SourceLocation);
-template Status MakeErrorImpl<15>(string_view, SourceLocation);
-template Status MakeErrorImpl<16>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<0>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<1>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<2>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<3>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<4>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<5>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<6>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<7>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<8>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<9>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<10>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<11>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<12>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<13>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<14>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<15>(string_view, SourceLocation);
+template Status MakeErrorStringViewImpl<16>(string_view, SourceLocation);
+
+// Same as above, but for rvalue strings.
+#ifndef SWIG
+// We use an int in the template parameter to shorten mangled names.
+template <int error_code>
+Status MakeErrorStringRvalueImpl(std::string&& message, SourceLocation loc) {
+  return Status(static_cast<StatusCode>(error_code), std::move(message), loc);
+}
+
+// Explicit instantiation for all the error codes.
+// If we add more error code, we need to add their values on this list.
+// Using ints here instead of static_cast<int>(StatusCode::kFoo) makes it easier
+// to see that the list is complete.
+template Status MakeErrorStringRvalueImpl<0>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<1>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<2>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<3>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<4>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<5>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<6>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<7>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<8>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<9>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<10>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<11>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<12>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<13>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<14>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<15>(std::string&&, SourceLocation);
+template Status MakeErrorStringRvalueImpl<16>(std::string&&, SourceLocation);
+#endif  // SWIG
+
 }  // namespace status_internal
 
 bool IsAborted(const Status& status) {
diff --git a/absl/status/status.h b/absl/status/status.h
index 3103e79..f86065a 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -469,8 +469,7 @@
   // Same as above but for rvalue string.
   // Note: using a template to disambiguate the case of matching string_view and
   // string&& (e.g. char*) as a template lowers the priority of the overload.
-  template <typename String,
-            typename = std::enable_if_t<std::is_same_v<String, std::string>>>
+  template <typename String, typename = status_internal::EnableIfString<String>>
   Status(absl::StatusCode code, String&& msg,
          absl::SourceLocation loc = SourceLocation::current());
 #endif  // SWIG
@@ -890,45 +889,176 @@
 // These convenience functions create an `absl::Status` object with an error
 // code as indicated by the associated function name, using the error message
 // passed in `message`.
+// Note: using a template for the rvalue message overload to disambiguate the
+// case of matching string_view and string&& (e.g. char*) as a template lowers
+// the priority of the overload.
+
+// AbortedError
 Status AbortedError(absl::string_view message,
                     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status AbortedError(String&& message,
+                    absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// AlreadyExistsError
 Status AlreadyExistsError(absl::string_view message,
                           absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status AlreadyExistsError(String&& message,
+                          absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// CancelledError
 Status CancelledError(absl::string_view message,
                       absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status CancelledError(String&& message,
+                      absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// DataLossError
 Status DataLossError(absl::string_view message,
                      absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status DataLossError(String&& message,
+                     absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// DeadlineExceededError
 Status DeadlineExceededError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status DeadlineExceededError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// FailedPreconditionError
 Status FailedPreconditionError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status FailedPreconditionError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// InternalError
 Status InternalError(absl::string_view message,
                      absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status InternalError(String&& message,
+                     absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// InvalidArgumentError
 Status InvalidArgumentError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status InvalidArgumentError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// NotFoundError
 Status NotFoundError(absl::string_view message,
                      absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status NotFoundError(String&& message,
+                     absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// OutOfRangeError
 Status OutOfRangeError(absl::string_view message,
                        absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status OutOfRangeError(String&& message,
+                       absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// PermissionDeniedError
 Status PermissionDeniedError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status PermissionDeniedError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// ResourceExhaustedError
 Status ResourceExhaustedError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status ResourceExhaustedError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// UnauthenticatedError
 Status UnauthenticatedError(
     absl::string_view message,
     absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status UnauthenticatedError(
+    String&& message, absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// UnavailableError
 Status UnavailableError(absl::string_view message,
                         absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status UnavailableError(String&& message,
+                        absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// UnimplementedError
 Status UnimplementedError(absl::string_view message,
                           absl::SourceLocation loc = SourceLocation::current());
+
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status UnimplementedError(String&& message,
+                          absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
+// UnknownError
 Status UnknownError(absl::string_view message,
                     absl::SourceLocation loc = SourceLocation::current());
 
+#ifndef SWIG
+template <typename String, typename = status_internal::EnableIfString<String>>
+Status UnknownError(String&& message,
+                    absl::SourceLocation loc = SourceLocation::current());
+#endif  // SWIG
+
 // ErrnoToStatusCode()
 //
 // Returns the StatusCode for `error_number`, which should be an `errno` value.
@@ -1143,110 +1273,339 @@
 namespace status_internal {
 // We use an int in the template parameter to shorten mangled names.
 template <int error_code>
-Status MakeErrorImpl(string_view message, SourceLocation loc);
+Status MakeErrorStringViewImpl(string_view message, SourceLocation loc);
 // Make the instantiations extern to reduce bloat on callers.
 #ifndef SWIG
-extern template Status MakeErrorImpl<0>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<1>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<2>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<3>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<4>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<5>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<6>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<7>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<8>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<9>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<10>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<11>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<12>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<13>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<14>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<15>(string_view, SourceLocation);
-extern template Status MakeErrorImpl<16>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<0>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<1>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<2>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<3>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<4>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<5>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<6>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<7>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<8>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<9>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<10>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<11>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<12>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<13>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<14>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<15>(string_view, SourceLocation);
+extern template Status MakeErrorStringViewImpl<16>(string_view, SourceLocation);
 #endif  // SWIG
 
 template <StatusCode error_code>
-Status MakeError(string_view message, SourceLocation loc) {
-  Status out = MakeErrorImpl<static_cast<int>(error_code)>(message, loc);
+Status MakeErrorFromStringView(string_view message, SourceLocation loc) {
+  Status out =
+      MakeErrorStringViewImpl<static_cast<int>(error_code)>(message, loc);
   // -Wassume warning complains about potential side effects of `ok()`, so use a
   // local to avoid that.
   [[maybe_unused]] bool ok = out.ok();
   ABSL_ASSUME(!ok);
   return out;
 }
+
+// Same as above, but for rvalue std::string.
+#ifndef SWIG
+// We use an int in the template parameter to shorten mangled names.
+template <int error_code>
+Status MakeErrorStringRvalueImpl(std::string&& message, SourceLocation loc);
+// Make the instantiations extern to reduce bloat on callers.
+extern template Status MakeErrorStringRvalueImpl<0>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<1>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<2>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<3>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<4>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<5>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<6>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<7>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<8>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<9>(std::string&&,
+                                                    SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<10>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<11>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<12>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<13>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<14>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<15>(std::string&&,
+                                                     SourceLocation);
+extern template Status MakeErrorStringRvalueImpl<16>(std::string&&,
+                                                     SourceLocation);
+
+template <StatusCode error_code, typename String>
+Status MakeErrorFromStringRvalue(String&& message, SourceLocation loc) {
+  static_assert(std::is_same_v<String&&, std::string&&>,
+                "`message` should be std::string&&");
+  Status out = MakeErrorStringRvalueImpl<static_cast<int>(error_code)>(
+      std::forward<String>(message), loc);
+  // -Wassume warning complains about potential side effects of `ok()`, so use a
+  // local to avoid that.
+  [[maybe_unused]] bool ok = out.ok();
+  ABSL_ASSUME(!ok);
+  return out;
+}
+#endif  // SWIG
+
 }  // namespace status_internal
 
 // Inline implementations to give the compiler static knowledge about the
 // objects.
+
+// AbortedError
 inline Status AbortedError(absl::string_view message,
                            absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kAborted>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kAborted>(message,
+                                                                        loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status AbortedError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kAborted>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// AlreadyExistsError
 inline Status AlreadyExistsError(absl::string_view message,
                                  absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kAlreadyExists>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kAlreadyExists>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status AlreadyExistsError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kAlreadyExists>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// CancelledError
 inline Status CancelledError(absl::string_view message,
                              absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kCancelled>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kCancelled>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status CancelledError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kCancelled>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// DataLossError
 inline Status DataLossError(absl::string_view message,
                             absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kDataLoss>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kDataLoss>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status DataLossError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kDataLoss>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// DeadlineExceededError
 inline Status DeadlineExceededError(absl::string_view message,
                                     absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kDeadlineExceeded>(message,
-                                                                   loc);
+  return status_internal::MakeErrorFromStringView<
+      StatusCode::kDeadlineExceeded>(message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status DeadlineExceededError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kDeadlineExceeded>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// FailedPreconditionError
 inline Status FailedPreconditionError(absl::string_view message,
                                       absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kFailedPrecondition>(message,
-                                                                     loc);
+  return status_internal::MakeErrorFromStringView<
+      StatusCode::kFailedPrecondition>(message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status FailedPreconditionError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kFailedPrecondition>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// InternalError
 inline Status InternalError(absl::string_view message,
                             absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kInternal>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kInternal>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status InternalError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kInternal>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// InvalidArgumentError
 inline Status InvalidArgumentError(absl::string_view message,
                                    absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kInvalidArgument>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kInvalidArgument>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status InvalidArgumentError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kInvalidArgument>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// NotFoundError
 inline Status NotFoundError(absl::string_view message,
                             absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kNotFound>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kNotFound>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status NotFoundError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kNotFound>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// OutOfRangeError
 inline Status OutOfRangeError(absl::string_view message,
                               absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kOutOfRange>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kOutOfRange>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status OutOfRangeError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kOutOfRange>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// PermissionDeniedError
 inline Status PermissionDeniedError(absl::string_view message,
                                     absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kPermissionDenied>(message,
-                                                                   loc);
+  return status_internal::MakeErrorFromStringView<
+      StatusCode::kPermissionDenied>(message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status PermissionDeniedError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kPermissionDenied>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// ResourceExhaustedError
 inline Status ResourceExhaustedError(absl::string_view message,
                                      absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kResourceExhausted>(message,
-                                                                    loc);
+  return status_internal::MakeErrorFromStringView<
+      StatusCode::kResourceExhausted>(message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status ResourceExhaustedError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kResourceExhausted>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// UnauthenticatedError
 inline Status UnauthenticatedError(absl::string_view message,
                                    absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kUnauthenticated>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kUnauthenticated>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status UnauthenticatedError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<
+      StatusCode::kUnauthenticated>(std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// UnavailableError
 inline Status UnavailableError(absl::string_view message,
                                absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kUnavailable>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kUnavailable>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status UnavailableError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnavailable>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// UnimplementedError
 inline Status UnimplementedError(absl::string_view message,
                                  absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kUnimplemented>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kUnimplemented>(
+      message, loc);
 }
+
+#ifndef SWIG
+template <typename String, typename>
+Status UnimplementedError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnimplemented>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
+// UnknownError
 inline Status UnknownError(absl::string_view message,
                            absl::SourceLocation loc) {
-  return status_internal::MakeError<StatusCode::kUnknown>(message, loc);
+  return status_internal::MakeErrorFromStringView<StatusCode::kUnknown>(message,
+                                                                        loc);
 }
 
+#ifndef SWIG
+template <typename String, typename>
+Status UnknownError(String&& message, absl::SourceLocation loc) {
+  return status_internal::MakeErrorFromStringRvalue<StatusCode::kUnknown>(
+      std::forward<String>(message), loc);
+}
+#endif  // SWIG
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/status/status_benchmark.cc b/absl/status/status_benchmark.cc
index 0404db1..b001e63 100644
--- a/absl/status/status_benchmark.cc
+++ b/absl/status/status_benchmark.cc
@@ -57,4 +57,14 @@
 }
 BENCHMARK(BM_LongMessageRValue);
 
+void BM_LongMessageRValueConvenienceFn(benchmark::State& state) {
+  for (auto _ : state) {
+    std::string msg(100, 'X');
+    benchmark::DoNotOptimize(msg);
+    absl::Status s = absl::InvalidArgumentError(std::move(msg));
+    benchmark::DoNotOptimize(s);
+  }
+}
+BENCHMARK(BM_LongMessageRValueConvenienceFn);
+
 }  // namespace
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc
index ddf0be0..c4679d6 100644
--- a/absl/status/status_test.cc
+++ b/absl/status/status_test.cc
@@ -19,6 +19,7 @@
 #include <array>
 #include <cstddef>
 #include <sstream>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -46,41 +47,82 @@
 }
 
 // This structure holds the details for testing a single error code,
-// its creator, and its classifier.
+// its creator, its rvalue creator, and its classifier.
 struct ErrorTest {
   absl::StatusCode code;
   using Creator = absl::Status (*)(absl::string_view, absl::SourceLocation);
-  using Classifier = bool (*)(const absl::Status&);
   Creator creator;
+  using CreatorRValue = absl::Status (*)(std::string&&, absl::SourceLocation);
+  CreatorRValue creator_rvalue;
+  using Classifier = bool (*)(const absl::Status&);
   Classifier classifier;
 };
 
 constexpr ErrorTest kErrorTests[]{
-    {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},
-    {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},
-    {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,
-     absl::IsInvalidArgument},
-    {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,
-     absl::IsDeadlineExceeded},
-    {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},
-    {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,
-     absl::IsAlreadyExists},
-    {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,
-     absl::IsPermissionDenied},
-    {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,
-     absl::IsResourceExhausted},
-    {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,
-     absl::IsFailedPrecondition},
-    {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},
-    {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},
-    {absl::StatusCode::kUnimplemented, absl::UnimplementedError,
-     absl::IsUnimplemented},
-    {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},
-    {absl::StatusCode::kUnavailable, absl::UnavailableError,
-     absl::IsUnavailable},
-    {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},
-    {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,
-     absl::IsUnauthenticated},
+    {absl::StatusCode::kCancelled,           //
+     absl::CancelledError,                   //
+     absl::CancelledError,                   //
+     absl::IsCancelled},                     //
+    {absl::StatusCode::kUnknown,             //
+     absl::UnknownError,                     //
+     absl::UnknownError,                     //
+     absl::IsUnknown},                       //
+    {absl::StatusCode::kInvalidArgument,     //
+     absl::InvalidArgumentError,             //
+     absl::InvalidArgumentError,             //
+     absl::IsInvalidArgument},               //
+    {absl::StatusCode::kDeadlineExceeded,    //
+     absl::DeadlineExceededError,            //
+     absl::DeadlineExceededError,            //
+     absl::IsDeadlineExceeded},              //
+    {absl::StatusCode::kNotFound,            //
+     absl::NotFoundError,                    //
+     absl::NotFoundError,                    //
+     absl::IsNotFound},                      //
+    {absl::StatusCode::kAlreadyExists,       //
+     absl::AlreadyExistsError,               //
+     absl::AlreadyExistsError,               //
+     absl::IsAlreadyExists},                 //
+    {absl::StatusCode::kPermissionDenied,    //
+     absl::PermissionDeniedError,            //
+     absl::PermissionDeniedError,            //
+     absl::IsPermissionDenied},              //
+    {absl::StatusCode::kResourceExhausted,   //
+     absl::ResourceExhaustedError,           //
+     absl::ResourceExhaustedError,           //
+     absl::IsResourceExhausted},             //
+    {absl::StatusCode::kFailedPrecondition,  //
+     absl::FailedPreconditionError,          //
+     absl::FailedPreconditionError,          //
+     absl::IsFailedPrecondition},            //
+    {absl::StatusCode::kAborted,             //
+     absl::AbortedError,                     //
+     absl::AbortedError,                     //
+     absl::IsAborted},                       //
+    {absl::StatusCode::kOutOfRange,          //
+     absl::OutOfRangeError,                  //
+     absl::OutOfRangeError,                  //
+     absl::IsOutOfRange},                    //
+    {absl::StatusCode::kUnimplemented,       //
+     absl::UnimplementedError,               //
+     absl::UnimplementedError,               //
+     absl::IsUnimplemented},                 //
+    {absl::StatusCode::kInternal,            //
+     absl::InternalError,                    //
+     absl::InternalError,                    //
+     absl::IsInternal},                      //
+    {absl::StatusCode::kUnavailable,         //
+     absl::UnavailableError,                 //
+     absl::UnavailableError,                 //
+     absl::IsUnavailable},                   //
+    {absl::StatusCode::kDataLoss,            //
+     absl::DataLossError,                    //
+     absl::DataLossError,                    //
+     absl::IsDataLoss},                      //
+    {absl::StatusCode::kUnauthenticated,     //
+     absl::UnauthenticatedError,             //
+     absl::UnauthenticatedError,             //
+     absl::IsUnauthenticated},               //
 };
 
 TEST(Status, CreateAndClassify) {
@@ -96,9 +138,16 @@
     EXPECT_EQ(test.code, status.code());
     EXPECT_EQ(message, status.message());
 
+    // Testing the rvalue creator.
+    absl::Status status_rvalue = test.creator_rvalue(
+        std::string(message), absl::SourceLocation::current());
+    EXPECT_EQ(test.code, status_rvalue.code());
+    EXPECT_EQ(message, status_rvalue.message());
+
     // Ensure that the classifier returns true for a status produced by the
     // creator.
     EXPECT_TRUE(test.classifier(status));
+    EXPECT_TRUE(test.classifier(status_rvalue));
 
     // Ensure that the classifier returns false for status with a different
     // code.
@@ -111,6 +160,37 @@
   }
 }
 
+// Test that status convenience functions can be called with a string literal.
+// Doing so to make sure it's not ambiguous between the string_view and string&&
+// overloads.
+TEST(Status, StringLiteralCreation) {
+  EXPECT_EQ(absl::AbortedError("msg").code(), absl::StatusCode::kAborted);
+  EXPECT_EQ(absl::AlreadyExistsError("msg").code(),
+            absl::StatusCode::kAlreadyExists);
+  EXPECT_EQ(absl::CancelledError("msg").code(), absl::StatusCode::kCancelled);
+  EXPECT_EQ(absl::DataLossError("msg").code(), absl::StatusCode::kDataLoss);
+  EXPECT_EQ(absl::DeadlineExceededError("msg").code(),
+            absl::StatusCode::kDeadlineExceeded);
+  EXPECT_EQ(absl::FailedPreconditionError("msg").code(),
+            absl::StatusCode::kFailedPrecondition);
+  EXPECT_EQ(absl::InternalError("msg").code(), absl::StatusCode::kInternal);
+  EXPECT_EQ(absl::InvalidArgumentError("msg").code(),
+            absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(absl::NotFoundError("msg").code(), absl::StatusCode::kNotFound);
+  EXPECT_EQ(absl::OutOfRangeError("msg").code(), absl::StatusCode::kOutOfRange);
+  EXPECT_EQ(absl::PermissionDeniedError("msg").code(),
+            absl::StatusCode::kPermissionDenied);
+  EXPECT_EQ(absl::ResourceExhaustedError("msg").code(),
+            absl::StatusCode::kResourceExhausted);
+  EXPECT_EQ(absl::UnauthenticatedError("msg").code(),
+            absl::StatusCode::kUnauthenticated);
+  EXPECT_EQ(absl::UnavailableError("msg").code(),
+            absl::StatusCode::kUnavailable);
+  EXPECT_EQ(absl::UnimplementedError("msg").code(),
+            absl::StatusCode::kUnimplemented);
+  EXPECT_EQ(absl::UnknownError("msg").code(), absl::StatusCode::kUnknown);
+}
+
 TEST(Status, DefaultConstructor) {
   absl::Status status;
   EXPECT_TRUE(status.ok());
@@ -340,37 +420,37 @@
 
 TEST(Status, OstreamOperator) {
   absl::Status status(absl::StatusCode::kInternal, "fail");
-  { std::stringstream stream;
+  {
+    std::stringstream stream;
     stream << status;
-    EXPECT_THAT(stream.str(),
-                AllOf(HasSubstr("INTERNAL: fail"),
-                      HasSubstr("status_test.cc:")));
+    EXPECT_THAT(stream.str(), AllOf(HasSubstr("INTERNAL: fail"),
+                                    HasSubstr("status_test.cc:")));
   }
   status.SetPayload("foo", absl::Cord("bar"));
-  { std::stringstream stream;
+  {
+    std::stringstream stream;
     stream << status;
     EXPECT_THAT(stream.str(),
                 AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
                       HasSubstr("status_test.cc:")));
   }
   status.SetPayload("bar", absl::Cord("\377"));
-  { std::stringstream stream;
+  {
+    std::stringstream stream;
     stream << status;
-    EXPECT_THAT(stream.str(),
-                AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                      HasSubstr("[bar='\\xff']"),
-                      HasSubstr("status_test.cc:")));
+    EXPECT_THAT(
+        stream.str(),
+        AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+              HasSubstr("[bar='\\xff']"), HasSubstr("status_test.cc:")));
   }
 }
 
 TEST(Status, AbslStringify) {
   absl::Status status(absl::StatusCode::kInternal, "fail");
   EXPECT_THAT(absl::StrCat(status),
-              AllOf(HasSubstr("INTERNAL: fail"),
-                    HasSubstr("status_test.cc:")));
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("status_test.cc:")));
   EXPECT_THAT(absl::StrFormat("%v", status),
-              AllOf(HasSubstr("INTERNAL: fail"),
-                    HasSubstr("status_test.cc:")));
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("status_test.cc:")));
   EXPECT_EQ(absl::StrCat(status), absl::StrFormat("%v", status));
   status.SetPayload("foo", absl::Cord("bar"));
   EXPECT_THAT(absl::StrCat(status),
@@ -379,8 +459,7 @@
   status.SetPayload("bar", absl::Cord("\377"));
   EXPECT_THAT(absl::StrCat(status),
               AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                    HasSubstr("[bar='\\xff']"),
-                    HasSubstr("status_test.cc:")));
+                    HasSubstr("[bar='\\xff']"), HasSubstr("status_test.cc:")));
 }
 
 TEST(Status, OstreamEqStringify) {
@@ -867,8 +946,7 @@
   {
     // Status that ignores source location.
     absl::Status status_ignores_source_location[] = {
-        absl::Status(),
-        absl::Status(absl::StatusCode::kInternal, "")};
+        absl::Status(), absl::Status(absl::StatusCode::kInternal, "")};
     for (absl::Status& s : status_ignores_source_location) {
       for (int i = 0; i < max_iter; ++i) {
         s.AddSourceLocation(absl::SourceLocation::current());
@@ -967,27 +1045,27 @@
 
   s.SetPayload("bar", absl::Cord("\377"));
 
-  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
-              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                    HasSubstr("[bar='\\xff']"),
-                    HasSubstr(source_location_string),
-                    HasSubstr(source_location_stack)));
-  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload |
-                         absl::StatusToStringMode::kWithSourceLocation),
-              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                    HasSubstr("[bar='\\xff']"),
-                    HasSubstr(source_location_string),
-                    HasSubstr(source_location_stack)));
-  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation),
-              AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
-                    Not(HasSubstr("[bar='\\xff']")),
-                    HasSubstr(source_location_string),
-                    HasSubstr(source_location_stack)));
-  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),
-              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                    HasSubstr("[bar='\\xff']"),
-                    Not(HasSubstr(source_location_string)),
-                    Not(HasSubstr(source_location_stack))));
+  EXPECT_THAT(
+      s.ToString(absl::StatusToStringMode::kWithEverything),
+      AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+            HasSubstr("[bar='\\xff']"), HasSubstr(source_location_string),
+            HasSubstr(source_location_stack)));
+  EXPECT_THAT(
+      s.ToString(absl::StatusToStringMode::kWithPayload |
+                 absl::StatusToStringMode::kWithSourceLocation),
+      AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+            HasSubstr("[bar='\\xff']"), HasSubstr(source_location_string),
+            HasSubstr(source_location_stack)));
+  EXPECT_THAT(
+      s.ToString(absl::StatusToStringMode::kWithSourceLocation),
+      AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
+            Not(HasSubstr("[bar='\\xff']")), HasSubstr(source_location_string),
+            HasSubstr(source_location_stack)));
+  EXPECT_THAT(
+      s.ToString(absl::StatusToStringMode::kWithPayload),
+      AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+            HasSubstr("[bar='\\xff']"), Not(HasSubstr(source_location_string)),
+            Not(HasSubstr(source_location_stack))));
 }
 
 TEST(Status, StackTracePayloadOverflow) {