The resulting type here is missing the N parameter, which prevents it from forwarding extent info. That constructor is explicit, so we have to name the type.
With that done, there's a single case of a span being reused with an incompatible extent size. Full necessary change is:
diff --git a/src/span.h b/src/span.h
index 62e035d2d35..5e34cd91909 100644
--- a/src/span.h
+++ b/src/span.h
@@ -105,7 +105,7 @@ template <typename B>
concept BasicByte = requires { UCharCast(std::span<B>{}.data()); };
// Helper function to safely convert a span to a span<[const] unsigned char>.
-template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) -> std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>> { return {UCharCast(s.data()), s.size()}; }
+template <typename T, size_t N> constexpr auto UCharSpanCast(std::span<T, N> s) { return std::span<std::remove_pointer_t<decltype(UCharCast(s.data()))>, N>{UCharCast(s.data()), s.size()}; }
/** Like the std::span constructor, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
template <typename V> constexpr auto MakeUCharSpan(const V& v) -> decltype(UCharSpanCast(std::span{v})) { return UCharSpanCast(std::span{v}); }
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index bc50bf408eb..0fa6f7d8e5a 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -160,8 +160,8 @@ BOOST_AUTO_TEST_CASE(parse_hex)
BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
const std::vector<std::byte> hex_literal_vector{operator""_hex_v<util::detail::Hex(HEX_PARSE_INPUT)>()};
- hex_literal_span = MakeUCharSpan(hex_literal_vector);
- BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_span.begin(), hex_literal_span.end(), expected.begin(), expected.end());
+ auto hex_literal_vec_span = MakeUCharSpan(hex_literal_vector);
+ BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_vec_span.begin(), hex_literal_vec_span.end(), expected.begin(), expected.end());
constexpr std::array<uint8_t, 65> hex_literal_array_uint8{operator""_hex_u8<util::detail::Hex(HEX_PARSE_INPUT)>()};
BOOST_CHECK_EQUAL_COLLECTIONS(hex_literal_array_uint8.begin(), hex_literal_array_uint8.end(), expected.begin(), expected.end());
Arguably this is a bug introduced in this PR, as all the other conversion functions forward the extent info correctly.