Allow ValidTraits to be 'inherited'

Real inheritance doesn't work with trait_helpers::AreValidTraits

I.e. this doesn't work:

struct ValidTraits {
  ValidTraits(TraitA);
};

struct ValidTraits2 : public ValidTraits {
  ValidTraits2(TraitB);
};


But we can make this work:

struct ValidTraits {
  ValidTraits(TraitA);
};

struct ValidTraits2 {
  ValidTraits2(ValidTraits);
  ValidTraits2(TraitB);
};

Unfortunately that doesn't work 3 levels deep, but it does fix
the requirements for the BrowserUIThreadScheduler.

Bug: 863341
Change-Id: I059c6db46be3363efcc57f1bee721e697231c888
Reviewed-on: https://chromium-review.googlesource.com/c/1400582
Commit-Queue: Alex Clarke <[email protected]>
Reviewed-by: François Doray <[email protected]>
Cr-Commit-Position: refs/heads/master@{#620720}
diff --git a/base/traits_bag.h b/base/traits_bag.h
index 7c079db2..4a75651f 100644
--- a/base/traits_bag.h
+++ b/base/traits_bag.h
@@ -155,11 +155,19 @@
 //   ValidTraits(MyTrait);
 //   ...
 // };
+//
+// You can 'inherit' valid traits like so:
+//
+// struct MoreValidTraits {
+//   MoreValidTraits(ValidTraits);  // Pull in traits from ValidTraits.
+//   MoreValidTraits(MyOtherTrait);
+//   ...
+// };
 template <class ValidTraits, class... ArgTypes>
 struct AreValidTraits
     : std::integral_constant<
           bool,
-          all_of({std::is_convertible<ArgTypes, ValidTraits>::value...})> {};
+          all_of({std::is_constructible<ValidTraits, ArgTypes>::value...})> {};
 
 // Helper to make getting an enum from a trait more readable.
 template <typename Enum, typename... Args>
diff --git a/base/traits_bag_unittest.cc b/base/traits_bag_unittest.cc
index 05fad0ae..63f5846 100644
--- a/base/traits_bag_unittest.cc
+++ b/base/traits_bag_unittest.cc
@@ -126,5 +126,19 @@
   EXPECT_EQ(c.enum_trait_a, EnumTraitA::C);
 }
 
+TEST(TraitsBagTest, ValidTraitInheritance) {
+  struct ValidTraitsA {
+    ValidTraitsA(EnumTraitA);
+  };
+
+  struct ValidTraitsB {
+    ValidTraitsB(ValidTraitsA);
+    ValidTraitsB(EnumTraitB);
+  };
+
+  static_assert(AreValidTraits<ValidTraitsA, EnumTraitA>(), "");
+  static_assert(AreValidTraits<ValidTraitsB, EnumTraitA, EnumTraitB>(), "");
+}
+
 }  // namespace trait_helpers
 }  // namespace base