[libcxx-commits] [clang] [libcxx] [Clang] Normalize constraints before checking for satisfaction (PR #161671)

Devon Loehr via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 3 14:11:16 PDT 2025


DKLoehr wrote:

After this PR we've started to see static-assert failures when building chromium. I've attached a minimized reproducer (from cvise, then manually cut down as much as I could).

The below code will fail after this PR, and succeed before it, when `clang++` is run with `-std=c++20`. The failure is
```
preprocessed.cc:38:15: error: static assertion failed due to requirement '!std::is_constructible_v<span<4>, array<int, 3>>'
   38 | static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
```

Unfortunately I don't totally understand the code myself, but this seems wrong: we certainly don't want to be able to initialize a 4-element thing from a 3-element thing, and the `FixedExtentConstructibleFromExtent` seems like it should be checking that the two numbers are equal.

Furthermore, we need _both_ static_asserts at the end of the file. Whichever happens second will fail, and if only one exists it will pass.

```
namespace std {
template <int __v>
struct integral_constant {
  static const int value = __v;
};

template <class _Tp, class... _Args>
constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);

template <class _From, class _To>
constexpr bool is_convertible_v = __is_convertible(_From, _To);

template <class>
struct tuple_size;

template <class _Tp>
constexpr decltype(sizeof(int)) tuple_size_v = tuple_size<_Tp>::value;
}  // namespace std

template <int N, int X>
concept FixedExtentConstructibleFromExtent = X == N;

template <int Extent>
struct span {
  int static constexpr extent = Extent;
  template <typename R, int N = std::tuple_size_v<R>>
    requires(FixedExtentConstructibleFromExtent<extent, N>)
  span(R);
};

template <class, int>
struct array {};

template <class _Tp, decltype(sizeof(int)) _Size>
struct std::tuple_size<array<_Tp, _Size>> : integral_constant<_Size> {};

static_assert(std::is_convertible_v<array<int, 3>, span<3>>);
static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
```

https://github.com/llvm/llvm-project/pull/161671


More information about the libcxx-commits mailing list