From 4dd45e29e92e1caaeff09435e47f1fedaf38236d Mon Sep 17 00:00:00 2001 From: Denis Yaroshevskiy Date: Mon, 7 Oct 2024 06:27:22 -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 | 35 +++++++++++++----- folly/algorithm/simd/detail/Traits.h | 4 +- folly/algorithm/simd/test/ContainsTest.cpp | 43 ++++++++++++++++++++++ 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/folly/algorithm/simd/Contains.h b/folly/algorithm/simd/Contains.h index 00756bb75ec..e9b9b47fb0d 100644 --- a/folly/algorithm/simd/Contains.h +++ b/folly/algorithm/simd/Contains.h @@ -38,6 +38,21 @@ template using std_range_value_t = typename std::iterator_traits()))>::value_type; +template +constexpr bool convertible_with_no_loss = (sizeof(From) <= sizeof(To)) && + ((std::is_signed_v && std::is_signed_v) || + (std::is_unsigned_v && std::is_unsigned_v) || + (std::is_unsigned_v && (sizeof(From) < sizeof(To)))); + +template +constexpr bool contains_haystack_needle_test_v = // + std::is_invocable_v && + has_integral_simd_friendly_equivalent_scalar_v> && + has_integral_simd_friendly_equivalent_scalar_v && + convertible_with_no_loss< + simd_friendly_equivalent_scalar_t, + simd_friendly_equivalent_scalar_t>>; + } // namespace detail /** @@ -53,23 +68,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..d4b7479dcd5 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,46 @@ 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>); + } // namespace not_invocable_tests template