From 59978fe2c159ade45a0195476780e315012bd60b Mon Sep 17 00:00:00 2001 From: Denis Yaroshevskiy Date: Mon, 7 Oct 2024 07:20:00 -0700 Subject: [PATCH] change contains interface to be more restrictive (#2309) Summary: previous interface allowed for implicit conversions. So it so happens that the user would have to guard against it. I think I better guard here. Differential Revision: D63979345 --- folly/algorithm/simd/Contains.h | 46 +++++++++++++++++---- folly/algorithm/simd/detail/Traits.h | 4 +- folly/algorithm/simd/test/ContainsTest.cpp | 48 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/folly/algorithm/simd/Contains.h b/folly/algorithm/simd/Contains.h index 00756bb75ec..3530e90c34e 100644 --- a/folly/algorithm/simd/Contains.h +++ b/folly/algorithm/simd/Contains.h @@ -38,6 +38,32 @@ template using std_range_value_t = typename std::iterator_traits()))>::value_type; +template +constexpr bool convertible_with_no_loss() { + if (sizeof(From) > sizeof(To)) { + return false; + } + if (std::is_signed_v) { + return std::is_signed_v; + } + + return is_unsigned_v || sizeof(From) < sizeof(To); +} + +template +constexpr bool contains_haystack_needle_test() { + if constexpr (!std::is_invocable_v) { + return false; + } else if constexpr (!has_integral_simd_friendly_equivalent_scalar_v) { + return false; + } else { + using simd_haystack_value = + simd_friendly_equivalent_scalar_t>; + using simd_needle = simd_friendly_equivalent_scalar_t; + return convertible_with_no_loss(); + } +} + } // namespace detail /** @@ -53,23 +79,25 @@ using std_range_value_t = typename std::iterator_traits>> - FOLLY_ERASE bool operator()(R&& r, detail::std_range_value_t x) const { + typename T, + typename = + std::enable_if_t()>> + FOLLY_ERASE bool operator()(R&& r, T x) const { auto castR = detail::asSimdFriendlyUint(folly::span(r)); - auto castX = detail::asSimdFriendlyUint(x); + using value_type = detail::std_range_value_t; - using T = decltype(castX); + auto castX = static_cast(x); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { return detail::containsU8(castR, castX); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { return detail::containsU16(castR, castX); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { return detail::containsU32(castR, castX); } else { static_assert( - std::is_same_v, "internal error, unknown type"); + std::is_same_v, + "internal error, unknown type"); return detail::containsU64(castR, castX); } } diff --git a/folly/algorithm/simd/detail/Traits.h b/folly/algorithm/simd/detail/Traits.h index f3e34cb7eee..dc9f1c8a63e 100644 --- a/folly/algorithm/simd/detail/Traits.h +++ b/folly/algorithm/simd/detail/Traits.h @@ -53,13 +53,13 @@ using simd_friendly_equivalent_scalar_t = std::enable_if_t< like_t>())>>; template -constexpr bool has_integral_simd_friendly_equivalent_scalar = +constexpr bool has_integral_simd_friendly_equivalent_scalar_v = std::is_integral_v< // void will return false decltype(findSimdFriendlyEquivalent>())>; template using unsigned_simd_friendly_equivalent_scalar_t = std::enable_if_t< - has_integral_simd_friendly_equivalent_scalar, + has_integral_simd_friendly_equivalent_scalar_v, like_t>>; template diff --git a/folly/algorithm/simd/test/ContainsTest.cpp b/folly/algorithm/simd/test/ContainsTest.cpp index 55f1966d458..2b8302c1c20 100644 --- a/folly/algorithm/simd/test/ContainsTest.cpp +++ b/folly/algorithm/simd/test/ContainsTest.cpp @@ -20,6 +20,9 @@ #include +#include +#include + namespace folly::simd { namespace not_invocable_tests { @@ -33,6 +36,51 @@ static_assert(std::is_invocable_v< // std::vector&, int>); +static_assert(std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + int>); + +static_assert(std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::int16_t>); + +static_assert(std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::uint16_t>); + +static_assert(!std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::uint32_t>); + +static_assert(!std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::int64_t>); + +static_assert(!std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::int16_t>); + +static_assert(std::is_invocable_v< // + folly::simd::contains_fn, + std::vector&, + std::uint16_t>); + +static_assert(!std::is_invocable_v< // + folly::simd::contains_fn, + std::list&, + std::int32_t>); + +static_assert(!std::is_invocable_v< // + folly::simd::contains_fn, + const std::vector>&, + std::vector>); + } // namespace not_invocable_tests template