[libcxx][span] Implement solution to LWG-3255

This implements the relaxed requirements on the std::array constructors of span,
where the type only needs to be convertible to the element type of the span.

Note that the previous tests were not sufficient, as the const array<T, n> constructor
was only tested for compile time and the array<T, N> only during runtime.

Restructure the tests so that we can test conversions as well as both constructors.

Differential Revision: https://reviews.llvm.org/D75706

Cr-Mirrored-From: https://chromium.googlesource.com/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: ab9f11168f55add345f29592ec0946ac2e5ae697
diff --git a/include/span b/include/span
index 1851ff3..7ae0bdb 100644
--- a/include/span
+++ b/include/span
@@ -212,8 +212,16 @@
         { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
 
     _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
-    _LIBCPP_INLINE_VISIBILITY constexpr span(      array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
-    _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+
+    template <class _OtherElementType,
+              enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+
+    template <class _OtherElementType,
+              enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
 
     template <class _Container>
     _LIBCPP_INLINE_VISIBILITY
@@ -386,13 +394,15 @@
     _LIBCPP_INLINE_VISIBILITY
     constexpr span(element_type (&__arr)[_Sz])          noexcept : __data{__arr}, __size{_Sz} {}
 
-    template <size_t _Sz>
+    template <class _OtherElementType, size_t _Sz,
+              enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
     _LIBCPP_INLINE_VISIBILITY
-    constexpr span(array<value_type, _Sz>& __arr)       noexcept : __data{__arr.data()}, __size{_Sz} {}
+    constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
-    template <size_t _Sz>
+    template <class _OtherElementType, size_t _Sz,
+              enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
     _LIBCPP_INLINE_VISIBILITY
-    constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
+    constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
     template <class _Container>
     _LIBCPP_INLINE_VISIBILITY
diff --git a/test/std/containers/views/span.cons/stdarray.pass.cpp b/test/std/containers/views/span.cons/stdarray.pass.cpp
index 88f46a8..a598253 100644
--- a/test/std/containers/views/span.cons/stdarray.pass.cpp
+++ b/test/std/containers/views/span.cons/stdarray.pass.cpp
@@ -68,49 +68,58 @@
     }
 }
 
-
-template <typename T>
-constexpr bool testConstexprSpan()
+template <typename T, typename U = T>
+constexpr bool testConstructorArray()
 {
-    constexpr std::array<T,2> val = { T(), T() };
-    ASSERT_NOEXCEPT(std::span<const T>   {val});
-    ASSERT_NOEXCEPT(std::span<const T, 2>{val});
-    std::span<const T>    s1{val};
-    std::span<const T, 2> s2{val};
-    return
-        s1.data() == &val[0] && s1.size() == 2
-    &&  s2.data() == &val[0] && s2.size() == 2;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    std::array<T,2> val;
+    std::array<U,2> val = { U(), U() };
     ASSERT_NOEXCEPT(std::span<T>   {val});
     ASSERT_NOEXCEPT(std::span<T, 2>{val});
     std::span<T>    s1{val};
     std::span<T, 2> s2{val};
-    assert(s1.data() == &val[0] && s1.size() == 2);
-    assert(s2.data() == &val[0] && s2.size() == 2);
+    return s1.data() == &val[0] && s1.size() == 2
+        && s2.data() == &val[0] && s2.size() == 2;
+}
+
+template <typename T, typename U = T>
+constexpr bool testConstructorConstArray()
+{
+    const std::array<U,2> val = { U(), U() };
+    ASSERT_NOEXCEPT(std::span<const T>   {val});
+    ASSERT_NOEXCEPT(std::span<const T, 2>{val});
+    std::span<const T>    s1{val};
+    std::span<const T, 2> s2{val};
+    return s1.data() == &val[0] && s1.size() == 2
+        && s2.data() == &val[0] && s2.size() == 2;
+}
+
+template <typename T>
+constexpr bool testConstructors() {
+    static_assert(testConstructorArray<T>(), "");
+    static_assert(testConstructorArray<const T, T>(), "");
+    static_assert(testConstructorConstArray<T>(), "");
+    static_assert(testConstructorConstArray<const T, T>(), "");
+
+    return testConstructorArray<T>()
+        && testConstructorArray<const T, T>()
+        && testConstructorConstArray<T>()
+        && testConstructorConstArray<const T, T>();
 }
 
 struct A{};
 
 int main(int, char**)
 {
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
+    assert(testConstructors<int>());
+    assert(testConstructors<long>());
+    assert(testConstructors<double>());
+    assert(testConstructors<A>());
 
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
+    assert(testConstructors<int*>());
+    assert(testConstructors<int* const>());
+    assert(testConstructors<const int*>());
+    assert(testConstructors<const int* const>());
 
     checkCV();
 
-  return 0;
+    return 0;
 }
diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html
index 91b17f0..2a0be14 100644
--- a/www/cxx2a_status.html
+++ b/www/cxx2a_status.html
@@ -490,7 +490,7 @@
 	<tr><td><a href="https://wg21.link/LWG3251">3251</a></td><td>Are <tt>std::format</tt> alignment specifiers applied to string arguments?</td><td>Prague</td><td></td></tr>
 	<tr><td><a href="https://wg21.link/LWG3252">3252</a></td><td>Parse locale's aware modifiers for commands are not consistent with POSIX spec</td><td>Prague</td><td></td></tr>
 	<tr><td><a href="https://wg21.link/LWG3254">3254</a></td><td>Strike <tt>stop_token</tt>'s <tt>operator!=</tt></td><td>Prague</td><td></td></tr>
-	<tr><td><a href="https://wg21.link/LWG3255">3255</a></td><td><tt>span</tt>'s <tt>array</tt> constructor is too strict</td><td>Prague</td><td></td></tr>
+	<tr><td><a href="https://wg21.link/LWG3255">3255</a></td><td><tt>span</tt>'s <tt>array</tt> constructor is too strict</td><td>Prague</td><td>Complete</td></tr>
 	<tr><td><a href="https://wg21.link/LWG3260">3260</a></td><td><tt>year_month*</tt> arithmetic rejects durations convertible to years</td><td>Prague</td><td></td></tr>
 	<tr><td><a href="https://wg21.link/LWG3262">3262</a></td><td>Formatting of negative durations is not specified</td><td>Prague</td><td></td></tr>
 	<tr><td><a href="https://wg21.link/LWG3264">3264</a></td><td><tt>sized_range</tt> and <tt>ranges::size</tt> redundantly use <tt>disable_sized_range</tt></td><td>Prague</td><td></td></tr>