Snap for 8253222 from dbe499e5997f5d02ebbc3fd3884c349796175f61 to sdk-release

Change-Id: Ie37e24f1fdc416ff6bc978446cf3e4a756f780d2
diff --git a/Android.bp b/Android.bp
index c98cd21..ef56692 100644
--- a/Android.bp
+++ b/Android.bp
@@ -248,6 +248,37 @@
     test_suites: ["device_tests"],
 }
 
+// Can be removed when we move to c++20
+cc_test {
+    name: "libbase_result_constraint_test",
+    defaults: ["libbase_cflags_defaults"],
+    host_supported: true,
+    srcs: [
+        "result_test_constraint.cpp",
+    ],
+    target: {
+        android: {
+            sanitize: {
+                misc_undefined: ["integer"],
+            },
+        },
+    },
+    cpp_std: "gnu++20",
+    local_include_dirs: ["."],
+    shared_libs: ["libbase"],
+    static_libs: ["libgmock"],
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+    test_suites: ["device-tests"],
+}
+
 cc_benchmark {
     name: "libbase_benchmark",
     defaults: ["libbase_cflags_defaults"],
diff --git a/include/android-base/errors.h b/include/android-base/errors.h
index f67e6eb..61fdbd8 100644
--- a/include/android-base/errors.h
+++ b/include/android-base/errors.h
@@ -69,6 +69,9 @@
 //
 // Actually this can be used for any type as long as the OkOrFail<T> contract is satisfied. See
 // below.
+// If implicit conversion compilation errors occur involving a value type with a templated
+// forwarding ref ctor, compilation with cpp20 or explicitly converting to the desired
+// return type is required.
 #define OR_RETURN(expr)                                                                 \
   ({                                                                                    \
     decltype(expr)&& tmp = (expr);                                                      \
@@ -109,7 +112,7 @@
 
 // The OkOrFail contract for a type T. This must be implemented for a type T if you want to use
 // OR_RETURN(stmt) where stmt evalues to a value of type T.
-template <typename T>
+template <typename T, typename = void>
 struct OkOrFail {
   // Checks if T is ok or fail.
   static bool IsOk(const T&);
diff --git a/include/android-base/result.h b/include/android-base/result.h
index a5016b9..9715a8c 100644
--- a/include/android-base/result.h
+++ b/include/android-base/result.h
@@ -96,6 +96,7 @@
 
 #include <sstream>
 #include <string>
+#include <type_traits>
 
 #include "android-base/errors.h"
 #include "android-base/expected.h"
@@ -297,9 +298,93 @@
 
 // Specialization of android::base::OkOrFail<V> for V = Result<T, E>. See android-base/errors.h
 // for the contract.
-template <typename T, typename E>
-struct OkOrFail<Result<T, E>> {
-  typedef Result<T, E> V;
+
+namespace impl {
+template <typename U>
+using Code = std::decay_t<decltype(std::declval<U>().error().code())>;
+
+template <typename U>
+using ErrorType = std::decay_t<decltype(std::declval<U>().error())>;
+
+template <typename U>
+constexpr bool IsNumeric = std::is_integral_v<U> || std::is_floating_point_v<U> ||
+                           (std::is_enum_v<U> && std::is_convertible_v<U, size_t>);
+
+// This base class exists to take advantage of shadowing
+// We include the conversion in this base class so that if the conversion in NumericConversions
+// overlaps, we (arbitrarily) choose the implementation in NumericConversions due to shadowing.
+template <typename T>
+struct ConversionBase {
+  ErrorType<T> error_;
+  // T is a expected<U, ErrorType<T>>.
+  operator const T() const && {
+    return unexpected(std::move(error_));
+  }
+
+  operator const Code<T>() const && {
+    return error_.code();
+  }
+
+};
+
+// User defined conversions can be followed by numeric conversions
+// Although we template specialize for the exact code type, we need
+// specializations for conversions to all numeric types to avoid an
+// ambiguous conversion sequence.
+template <typename T, typename = void>
+struct NumericConversions : public ConversionBase<T> {};
+template <typename T>
+struct NumericConversions<T,
+    std::enable_if_t<impl::IsNumeric<impl::Code<T>>>
+    > : public ConversionBase<T>
+{
+#pragma push_macro("SPECIALIZED_CONVERSION")
+#define SPECIALIZED_CONVERSION(type)\
+  operator const expected<type, ErrorType<T>>() const &&\
+  { return unexpected(std::move(this->error_));}
+
+  SPECIALIZED_CONVERSION(int)
+  SPECIALIZED_CONVERSION(short int)
+  SPECIALIZED_CONVERSION(unsigned short int)
+  SPECIALIZED_CONVERSION(unsigned int)
+  SPECIALIZED_CONVERSION(long int)
+  SPECIALIZED_CONVERSION(unsigned long int)
+  SPECIALIZED_CONVERSION(long long int)
+  SPECIALIZED_CONVERSION(unsigned long long int)
+  SPECIALIZED_CONVERSION(bool)
+  SPECIALIZED_CONVERSION(char)
+  SPECIALIZED_CONVERSION(unsigned char)
+  SPECIALIZED_CONVERSION(signed char)
+  SPECIALIZED_CONVERSION(wchar_t)
+  SPECIALIZED_CONVERSION(char16_t)
+  SPECIALIZED_CONVERSION(char32_t)
+  SPECIALIZED_CONVERSION(float)
+  SPECIALIZED_CONVERSION(double)
+  SPECIALIZED_CONVERSION(long double)
+
+#undef SPECIALIZED_CONVERSION
+#pragma pop_macro("SPECIALIZED_CONVERSION")
+  // For debugging purposes
+  using IsNumericT = std::true_type;
+};
+
+#ifdef __cpp_concepts
+template<class U>
+concept Trivial = std::is_same_v<U, U>;
+#endif
+} // namespace impl
+
+template <typename T, typename E, bool include_message>
+struct OkOrFail<Result<T, E, include_message>>
+    : public impl::NumericConversions<Result<T, E, include_message>> {
+  using V = Result<T, E, include_message>;
+  using Err = impl::ErrorType<V>;
+  using C = impl::Code<V>;
+private:
+   OkOrFail(Err&& v): impl::NumericConversions<V>{std::move(v)} {}
+   OkOrFail(const OkOrFail& other) = delete;
+   OkOrFail(const OkOrFail&& other) = delete;
+public:
   // Checks if V is ok or fail
   static bool IsOk(const V& val) { return val.ok(); }
 
@@ -307,20 +392,23 @@
   static T Unwrap(V&& val) { return std::move(val.value()); }
 
   // Consumes V when it's a fail value
-  static OkOrFail<V> Fail(V&& v) {
+  static const OkOrFail<V> Fail(V&& v) {
     assert(!IsOk(v));
-    return OkOrFail<V>{std::move(v)};
+    return OkOrFail<V>{std::move(v.error())};
   }
-  V val_;
 
-  // Turns V into S (convertible from E) or Result<U, E>
-  template <typename S, typename = std::enable_if_t<std::is_convertible_v<E, S>>>
-  operator S() && {
-    return val_.error().code();
+  // We specialize as much as possible to avoid ambiguous conversion with
+  // templated expected ctor
+  operator const Result<C, E, include_message>() const && {
+    return unexpected(std::move(this->error_));
   }
+#ifdef __cpp_concepts
+  template <impl::Trivial U>
+#else
   template <typename U>
-  operator Result<U, E>() && {
-    return val_.error();
+#endif
+  operator const Result<U, E, include_message>() const && {
+    return unexpected(std::move(this->error_));
   }
 
   static std::string ErrorMessage(const V& val) { return val.error().message(); }
diff --git a/include/android-base/silent_death_test.h b/include/android-base/silent_death_test.h
index 16f99ef..261fa74 100644
--- a/include/android-base/silent_death_test.h
+++ b/include/android-base/silent_death_test.h
@@ -26,15 +26,41 @@
 #define sigaction64 sigaction
 #endif
 
-// Disables debuggerd stack traces to speed up death tests, make them less
-// noisy in logcat, and avoid expected deaths from showing up in stability metrics.
+// INTRODUCTION
+//
+// It can be useful to disable debuggerd stack traces/tombstones in death tests.
+// Reasons include:
+//
+//   1. speeding up death tests
+//   2. reducing the noise in logcat (for humans)
+//   3. avoiding bots from thinking that expected deaths should be reported in
+//      stability metrics/have bugs auto-filed
 //
 // When writing new death tests, inherit the test suite from SilentDeathTest
-// defined below. Only use ScopedSilentDeath in a test case/suite if changing the
-// test base from testing::Test to SilentDeathTest adds additional complextity when
+// defined below.
+//
+// Only use ScopedSilentDeath in a test case/suite if changing the test base
+// class from testing::Test to SilentDeathTest adds additional complextity when
 // test suite code is shared between death and non-death tests.
 //
-// For example, use ScopedSilentDeath if you have:
+// EXAMPLES
+//
+// For example, use SilentDeathTest for this simple case where there's no shared
+// setup or teardown:
+//
+//   using FooDeathTest = SilentDeathTest;
+//
+//   TEST(FooTest, DoesThis) {
+//     // normal test
+//   }
+//
+//   TEST_F(FooDeathTest, DoesThat) {
+//     // death test
+//   }
+//
+// Alternatively, use ScopedSilentDeath if you already have a Test subclass for
+// shared setup or teardown:
+//
 //   class FooTest : public testing::Test { ... /* shared setup/teardown */ };
 //
 //   using FooDeathTest = FooTest;
@@ -43,10 +69,32 @@
 //     // normal test
 //   }
 //
-//   TEST_F (FooDeathTest, DoesThat) {
+//   TEST_F(FooDeathTest, DoesThat) {
 //     ScopedSilentDeath _silentDeath;
 //     // death test
 //   }
+//
+// NOTES
+//
+// When writing death tests, consider using ASSERT_EXIT() and EXPECT_EXIT()
+// rather than the more obvious ASSERT_DEATH()/EXPECT_DEATH() macros... The
+// advantage is that you can specify a regular expression that you expect
+// the abort message to match, and can be explicit about what signal you expect
+// to die with, and you can also test for *successful* exits too. Examples:
+//
+//   ASSERT_DEATH(foo(), "some text\\. some more\\.");
+//
+//   ASSERT_EXIT(bar(), testing::ExitedWithCode(0), "Success");
+//
+//   ASSERT_EXIT(baz(), testing::KilledBySignal(SIGABRT),
+//               "expected detail message \\(blah\\)");
+//
+// As you can see the regular expression functionality is there for
+// ASSERT_DEATH() too, but it's important to realize that it's a regular
+// expression, so (as in the first and third examples), you'll need to quote
+// any metacharacters (and because it's a string literal, you'll either need
+// extra quoting or want to use a raw string).
+
 class ScopedSilentDeath {
  public:
   ScopedSilentDeath() {
@@ -68,11 +116,6 @@
   struct sigaction64 previous_;
 };
 
-// When writing death tests, use `using myDeathTest = SilentDeathTest;` or inherit from
-// SilentDeathTest instead of inheriting from testing::Test yourself.
-//
-// Disables debuggerd stack traces to speed up death tests, make them less
-// noisy in logcat, and avoid expected deaths from showing up in stability metrics.
 class SilentDeathTest : public testing::Test {
  protected:
   void SetUp() override {
diff --git a/result_test.cpp b/result_test.cpp
index 47feeee..3b2b2e3 100644
--- a/result_test.cpp
+++ b/result_test.cpp
@@ -15,11 +15,13 @@
  */
 
 #include "android-base/result.h"
-
+#include <utils/ErrorsMacros.h>
 #include "errno.h"
 
 #include <istream>
+#include <memory>
 #include <string>
+#include <type_traits>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -281,6 +283,143 @@
   EXPECT_DEATH(OR_FATAL(success_or_fail(false)), "fail: A");
 }
 
+TEST(result, unwrap_ambiguous_int) {
+  const std::string firstSuccess{"a"};
+  constexpr int secondSuccess = 5;
+  auto enum_success_or_fail = [&](bool success) -> Result<std::string, StatusT> {
+    if (success) return firstSuccess;
+    return ResultError<StatusT>("Fail", 10);
+  };
+  auto f = [&](bool success) -> Result<int, StatusT> {
+    auto val = OR_RETURN(enum_success_or_fail(success));
+    EXPECT_EQ(firstSuccess, val);
+    return secondSuccess;
+  };
+
+  auto r = f(true);
+  ASSERT_TRUE(r.ok());
+  EXPECT_EQ(r.value(), secondSuccess);
+  auto s = f(false);
+  ASSERT_TRUE(!s.ok());
+  EXPECT_EQ(s.error().code(), 10);
+}
+
+TEST(result, unwrap_ambiguous_uint_conv) {
+  const std::string firstSuccess{"a"};
+  constexpr size_t secondSuccess = 5ull;
+  auto enum_success_or_fail = [&](bool success) -> Result<std::string, StatusT> {
+    if (success) return firstSuccess;
+    return ResultError<StatusT>("Fail", 10);
+  };
+
+  auto f = [&](bool success) -> Result<size_t, StatusT> {
+    auto val = OR_RETURN(enum_success_or_fail(success));
+    EXPECT_EQ(firstSuccess, val);
+    return secondSuccess;
+  };
+
+  auto r = f(true);
+  ASSERT_TRUE(r.ok());
+  EXPECT_EQ(r.value(), secondSuccess);
+  auto s = f(false);
+  ASSERT_TRUE(!s.ok());
+  EXPECT_EQ(s.error().code(), 10);
+}
+
+struct IntConst {
+    int val_;
+    template <typename T, typename = std::enable_if_t<std::is_convertible_v<T, int>>>
+    IntConst(T&& val) : val_(val) {}
+    operator status_t() {return val_;}
+};
+
+TEST(result, unwrap_ambiguous_constructible) {
+  constexpr int firstSuccess = 5;
+  constexpr int secondSuccess = 7;
+  struct A {
+    A (int val) : val_(val) {}
+    operator status_t() { return 0; }
+    int val_;
+  };
+  // If this returns Result<A, ...> instead of Result<IntConst, ...>,
+  // compilation fails unless we compile with c++20
+  auto enum_success_or_fail = [&](bool success) -> Result<IntConst, StatusT, false> {
+    if (success) return firstSuccess;
+    return ResultError<StatusT, false>(10);
+  };
+  auto f = [&](bool success) -> Result<IntConst, StatusT, false> {
+    auto val = OR_RETURN(enum_success_or_fail(success));
+    EXPECT_EQ(firstSuccess, val.val_);
+    return secondSuccess;
+  };
+  auto r = f(true);
+  EXPECT_EQ(r.value().val_, secondSuccess);
+  auto s = f(false);
+  EXPECT_EQ(s.error().code(), 10);
+}
+
+struct Dangerous {};
+struct ImplicitFromDangerous {
+  ImplicitFromDangerous(Dangerous);
+};
+template <typename U>
+struct Templated {
+    U val_;
+    template <typename T, typename=std::enable_if_t<std::is_convertible_v<T, U>>>
+    Templated(T val) : val_(val) {}
+};
+
+
+TEST(result, dangerous_result_conversion) {
+  ResultError<Dangerous, false> error {Dangerous{}};
+  Result<Templated<Dangerous>, Dangerous, false> surprise {error};
+  EXPECT_TRUE(!surprise.ok());
+  Result<Templated<ImplicitFromDangerous>, Dangerous, false> surprise2 {error};
+  EXPECT_TRUE(!surprise2.ok());
+}
+
+TEST(result, generic_convertible) {
+  const std::string firstSuccess{"a"};
+  struct A {};
+  struct B {
+    operator A() {return A{};}
+  };
+
+  auto enum_success_or_fail = [&](bool success) -> Result<std::string, B> {
+    if (success) return firstSuccess;
+    return ResultError<B>("Fail", B{});
+  };
+  auto f = [&](bool success) -> Result<A, B> {
+    auto val = OR_RETURN(enum_success_or_fail(success));
+    EXPECT_EQ(firstSuccess, val);
+    return A{};
+  };
+
+  auto r = f(true);
+  EXPECT_TRUE(r.ok());
+  auto s = f(false);
+  EXPECT_TRUE(!s.ok());
+}
+
+TEST(result, generic_exact) {
+  const std::string firstSuccess{"a"};
+  struct A {};
+  auto enum_success_or_fail = [&](bool success) -> Result<std::string, A> {
+    if (success) return firstSuccess;
+    return ResultError<A>("Fail", A{});
+  };
+  auto f = [&](bool success) -> Result<A, A> {
+    auto val = OR_RETURN(enum_success_or_fail(success));
+    EXPECT_EQ(firstSuccess, val);
+    return A{};
+  };
+
+  auto r = f(true);
+  EXPECT_TRUE(r.ok());
+  auto s = f(false);
+  EXPECT_TRUE(!s.ok());
+}
+
 struct MyData {
   const int data;
   static int copy_constructed;
@@ -309,6 +448,27 @@
   }();
 }
 
+TEST(result, supports_move_only_type) {
+  auto f = [](bool success) -> Result<std::unique_ptr<std::string>> {
+    if (success) return std::make_unique<std::string>("hello");
+    return Error() << "error";
+  };
+
+  auto g = [&](bool success) -> Result<std::unique_ptr<std::string>> {
+    auto r = OR_RETURN(f(success));
+    EXPECT_EQ("hello", *(r.get()));
+    return std::make_unique<std::string>("world");
+  };
+
+  auto s = g(true);
+  EXPECT_RESULT_OK(s);
+  EXPECT_EQ("world", *(s->get()));
+
+  auto t = g(false);
+  EXPECT_FALSE(t.ok());
+  EXPECT_EQ("error", t.error().message());
+}
+
 struct ConstructorTracker {
   static size_t constructor_called;
   static size_t copy_constructor_called;
diff --git a/result_test_constraint.cpp b/result_test_constraint.cpp
new file mode 100644
index 0000000..253a276
--- /dev/null
+++ b/result_test_constraint.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Since result has c++20 conditional behavior, we compile with std=c++20 to
+// ensure functionality in both cases. Instead of duplicating the file, we will
+// include, since this test is not linked against anything.
+// This test can be removed when we move to c++20.
+#include "result_test.cpp"