https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116471
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> --- That assertion originated in std::copy, where we needed to ensure that std::copy would be ill-formed for non-assignable types when we take the memcpy branch. That code was removed from std::copy in r13-6372-g822a11a1e642e0 (the PR108846 fix) but lives on in ranges::copy. It was needed in std::copy because the assignment might happen in a discarded statement, if we take the if-constexpr(__memcpyable) branch, and the memcpy would compile for types that should not be usable with std::copy. We don't need it in std::copy now, because even when we take the memcpy branch, there's still a non-discarded statement that does the assignment (for the 1-element case). You might be right that we never needed it in ranges::copy because it's already constrained correctly.