[dawn/common] Use C++20 concepts

Also removed the useless declaration of <type_traits> in many files.

Bug: 343500108
Change-Id: I0da8f77721b2d822a3722c02ab399aae94a7a71c
Skip-Clang-Tidy-Checks: google-explicit-constructor
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/246594
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn/common/Math.h b/src/dawn/common/Math.h
index 1673703..fbb2d7a 100644
--- a/src/dawn/common/Math.h
+++ b/src/dawn/common/Math.h
@@ -35,7 +35,6 @@
 
 #include <limits>
 #include <optional>
-#include <type_traits>
 
 #include "dawn/common/Assert.h"
 #include "dawn/common/Platform.h"
@@ -142,9 +141,8 @@
 
 float SRGBToLinear(float srgb);
 
-template <typename T1,
-          typename T2,
-          typename Enable = typename std::enable_if<sizeof(T1) == sizeof(T2)>::type>
+template <typename T1, typename T2>
+    requires(sizeof(T1) == sizeof(T2))
 constexpr bool IsSubset(T1 subset, T2 set) {
     T2 bitsAlsoInSet = subset & set;
     return bitsAlsoInSet == subset;
diff --git a/src/dawn/common/Numeric.h b/src/dawn/common/Numeric.h
index 4488136..c90014c 100644
--- a/src/dawn/common/Numeric.h
+++ b/src/dawn/common/Numeric.h
@@ -28,9 +28,9 @@
 #ifndef SRC_DAWN_COMMON_NUMERIC_H_
 #define SRC_DAWN_COMMON_NUMERIC_H_
 
+#include <concepts>
 #include <cstdint>
 #include <limits>
-#include <type_traits>
 
 #include "dawn/common/Assert.h"
 
@@ -59,7 +59,8 @@
 
 // Only defined for unsigned integers because that is all that is
 // needed at the time of writing.
-template <typename Dst, typename Src, typename = std::enable_if_t<std::is_unsigned_v<Src>>>
+template <typename Dst, typename Src>
+    requires std::unsigned_integral<Src>
 inline Dst checked_cast(const Src& value) {
     DAWN_ASSERT(value <= std::numeric_limits<Dst>::max());
     return static_cast<Dst>(value);
@@ -67,18 +68,15 @@
 
 // Returns if two inclusive integral ranges [x0, x1] and [y0, y1] have overlap.
 template <typename T>
+    requires std::integral<T>
 bool RangesOverlap(T x0, T x1, T y0, T y1) {
     DAWN_ASSERT(x0 <= x1 && y0 <= y1);
-    if constexpr (std::is_integral_v<T>) {
         // Two ranges DON'T have overlap if and only if:
         // 1. [x0, x1] [y0, y1], or
         // 2. [y0, y1] [x0, x1]
         // which is (x1 < y0 || y1 < x0)
         // The inverse of which ends in the following statement.
         return x0 <= y1 && y0 <= x1;
-    } else {
-        static_assert(std::is_integral_v<T>, "Unsupported type");
-    }
 }
 
 }  // namespace dawn
diff --git a/src/dawn/common/Range.h b/src/dawn/common/Range.h
index f4fd777..7326602 100644
--- a/src/dawn/common/Range.h
+++ b/src/dawn/common/Range.h
@@ -28,9 +28,6 @@
 #ifndef SRC_DAWN_COMMON_RANGE_H_
 #define SRC_DAWN_COMMON_RANGE_H_
 
-#include <type_traits>
-#include <utility>
-
 namespace dawn {
 
 // An iterator over a range of numbers. Simplified version of Python's range() iterator that works
diff --git a/src/dawn/common/RefBase.h b/src/dawn/common/RefBase.h
index e341006..74ff361 100644
--- a/src/dawn/common/RefBase.h
+++ b/src/dawn/common/RefBase.h
@@ -28,8 +28,8 @@
 #ifndef SRC_DAWN_COMMON_REFBASE_H_
 #define SRC_DAWN_COMMON_REFBASE_H_
 
+#include <concepts>
 #include <cstddef>
-#include <type_traits>
 #include <utility>
 
 #include "dawn/common/Assert.h"
@@ -95,23 +95,27 @@
     // Constructors from a RefBase<U>. Note that in the *-assignment operators this cannot be the
     // same as `other` because overload resolution rules would have chosen the *-assignement
     // operators defined with `other` == RefBase<T, Traits>.
-    template <typename U, typename UTraits, typename = typename std::is_convertible<U, T>::type>
+    template <typename U, typename UTraits>
+        requires std::convertible_to<U, T>
     RefBase(const RefBase<U, UTraits>& other) : mValue(other.mValue) {
         AddRef(other.mValue);
     }
 
-    template <typename U, typename UTraits, typename = typename std::is_convertible<U, T>::type>
+    template <typename U, typename UTraits>
+        requires std::convertible_to<U, T>
     RefBase<T, Traits>& operator=(const RefBase<U, UTraits>& other) {
         Set(other.mValue);
         return *this;
     }
 
-    template <typename U, typename UTraits, typename = typename std::is_convertible<U, T>::type>
+    template <typename U, typename UTraits>
+        requires std::convertible_to<U, T>
     RefBase(RefBase<U, UTraits>&& other) {
         mValue = other.Detach();
     }
 
-    template <typename U, typename UTraits, typename = typename std::is_convertible<U, T>::type>
+    template <typename U, typename UTraits>
+        requires std::convertible_to<U, T>
     RefBase<T, Traits>& operator=(RefBase<U, UTraits>&& other) {
         Release(mValue);
         mValue = other.Detach();
@@ -165,7 +169,8 @@
     template <typename U, typename UTraits>
     friend class RefBase;
 
-    template <typename U, typename UTraits, typename = typename std::is_convertible<U, T>::type>
+    template <typename U, typename UTraits>
+        requires std::convertible_to<U, T>
     static void CastImpl(RefBase<T, Traits>* ref, RefBase<U, UTraits>* other) {
         other->Acquire(static_cast<U>(ref->Detach()));
     }
diff --git a/src/dawn/common/RefCounted.h b/src/dawn/common/RefCounted.h
index cf062d2..419a592 100644
--- a/src/dawn/common/RefCounted.h
+++ b/src/dawn/common/RefCounted.h
@@ -30,7 +30,6 @@
 
 #include <atomic>
 #include <cstdint>
-#include <type_traits>
 
 namespace dawn {
 
diff --git a/src/dawn/common/Result.h b/src/dawn/common/Result.h
index 8000a0f..b2e6359 100644
--- a/src/dawn/common/Result.h
+++ b/src/dawn/common/Result.h
@@ -28,10 +28,10 @@
 #ifndef SRC_DAWN_COMMON_RESULT_H_
 #define SRC_DAWN_COMMON_RESULT_H_
 
+#include <concepts>
 #include <cstddef>
 #include <cstdint>
 #include <memory>
-#include <type_traits>
 #include <utility>
 #include <variant>
 
@@ -137,8 +137,10 @@
 
     // Support returning a Result<T*, E*> from a Result<TChild*, E*>
     template <typename TChild>
+        requires std::same_as<TChild, T> || std::derived_from<TChild, T>
     Result(Result<TChild*, E>&& other);
     template <typename TChild>
+        requires std::same_as<TChild, T> || std::derived_from<TChild, T>
     Result<T*, E>& operator=(Result<TChild*, E>&& other);
 
     ~Result();
@@ -194,14 +196,18 @@
                   "Result<Ref<T>, E> reserves two bits for tagging pointers");
 
     template <typename U>
+        requires std::convertible_to<U*, T*>
     Result(Ref<U>&& success);
     template <typename U>
+        requires std::convertible_to<U*, T*>
     Result(const Ref<U>& success);
     Result(std::unique_ptr<E> error);
 
     template <typename U>
+        requires std::convertible_to<U*, T*>
     Result(Result<Ref<U>, E>&& other);
     template <typename U>
+        requires std::convertible_to<U*, T*>
     Result<Ref<U>, E>& operator=(Result<Ref<U>, E>&& other);
 
     ~Result();
@@ -310,16 +316,16 @@
 
 template <typename T, typename E>
 template <typename TChild>
+    requires std::same_as<TChild, T> || std::derived_from<TChild, T>
 Result<T*, E>::Result(Result<TChild*, E>&& other) : mPayload(other.mPayload) {
     other.mPayload = detail::kEmptyPayload;
-    static_assert(std::is_same<T, TChild>::value || std::is_base_of<T, TChild>::value);
 }
 
 template <typename T, typename E>
 template <typename TChild>
+    requires std::same_as<TChild, T> || std::derived_from<TChild, T>
 Result<T*, E>& Result<T*, E>::operator=(Result<TChild*, E>&& other) {
     DAWN_ASSERT(mPayload == detail::kEmptyPayload);
-    static_assert(std::is_same<T, TChild>::value || std::is_base_of<T, TChild>::value);
     mPayload = other.mPayload;
     other.mPayload = detail::kEmptyPayload;
     return *this;
@@ -408,13 +414,13 @@
 // Implementation of Result<Ref<T>, E>
 template <typename T, typename E>
 template <typename U>
+    requires std::convertible_to<U*, T*>
 Result<Ref<T>, E>::Result(Ref<U>&& success)
-    : mPayload(detail::MakePayload(success.Detach(), detail::Success)) {
-    static_assert(std::is_convertible<U*, T*>::value);
-}
+    : mPayload(detail::MakePayload(success.Detach(), detail::Success)) {}
 
 template <typename T, typename E>
 template <typename U>
+    requires std::convertible_to<U*, T*>
 Result<Ref<T>, E>::Result(const Ref<U>& success) : Result(Ref<U>(success)) {}
 
 template <typename T, typename E>
@@ -423,15 +429,15 @@
 
 template <typename T, typename E>
 template <typename U>
+    requires std::convertible_to<U*, T*>
 Result<Ref<T>, E>::Result(Result<Ref<U>, E>&& other) : mPayload(other.mPayload) {
-    static_assert(std::is_convertible<U*, T*>::value);
     other.mPayload = detail::kEmptyPayload;
 }
 
 template <typename T, typename E>
 template <typename U>
+    requires std::convertible_to<U*, T*>
 Result<Ref<U>, E>& Result<Ref<T>, E>::operator=(Result<Ref<U>, E>&& other) {
-    static_assert(std::is_convertible<U*, T*>::value);
     DAWN_ASSERT(mPayload == detail::kEmptyPayload);
     mPayload = other.mPayload;
     other.mPayload = detail::kEmptyPayload;
diff --git a/src/dawn/common/ityp_array.h b/src/dawn/common/ityp_array.h
index 546050b..54a569c 100644
--- a/src/dawn/common/ityp_array.h
+++ b/src/dawn/common/ityp_array.h
@@ -31,7 +31,6 @@
 #include <array>
 #include <cstddef>
 #include <limits>
-#include <type_traits>
 #include <utility>
 
 #include "dawn/common/TypedInteger.h"
diff --git a/src/dawn/common/ityp_span.h b/src/dawn/common/ityp_span.h
index e6b364f..fe345f3 100644
--- a/src/dawn/common/ityp_span.h
+++ b/src/dawn/common/ityp_span.h
@@ -28,8 +28,6 @@
 #ifndef SRC_DAWN_COMMON_ITYP_SPAN_H_
 #define SRC_DAWN_COMMON_ITYP_SPAN_H_
 
-#include <type_traits>
-
 #include "dawn/common/TypedInteger.h"
 #include "dawn/common/UnderlyingType.h"
 
diff --git a/src/dawn/common/ityp_vector.h b/src/dawn/common/ityp_vector.h
index e7aee9b..83c21ac 100644
--- a/src/dawn/common/ityp_vector.h
+++ b/src/dawn/common/ityp_vector.h
@@ -29,7 +29,6 @@
 #define SRC_DAWN_COMMON_ITYP_VECTOR_H_
 
 #include <limits>
-#include <type_traits>
 #include <vector>
 
 #include "dawn/common/TypedInteger.h"