This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Add workaround to avoid breaking users of <span> when <ranges> are disabled
ClosedPublic

Authored by ldionne on Mar 14 2022, 10:54 AM.

Details

Summary

Back in 3a208c68942e, we implemented the range-based constructor for <span>.
However, in doing so, we removed a previous non-standard constructor that
we provided before shipping <ranges>. Unfortunately, that breaks code that
was relying on a range-based constructor until we ship all of <ranges>.

This patch reintroduces the old non-conforming constructors and tests
that were removed in 3a208c68942e and uses them whenever <ranges> is
not provided (e.g. in LLVM 14). This is only a temporary workaround
until we enable <ranges> by default in C++20, which should hopefully
happen by LLVM 15.

The goal is to cherry-pick this workaround back to the LLVM 14 release
branch, since I suspect the constructor removal may otherwise cause
breakage out there, like the breakage I saw internally.

We could have avoided this situation by waiting for C++20 to be finalized
before shipping std::span. For example, we could have guarded it with
something like _LIBCPP_HAS_NO_INCOMPLETE_RANGES to prevent users from
accidentally starting to depend on it before it is stable. We did not
have these mechanisms when std::span was first implemented, though.

Diff Detail

Event Timeline

ldionne created this revision.Mar 14 2022, 10:54 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 14 2022, 10:54 AM
ldionne requested review of this revision.Mar 14 2022, 10:54 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 14 2022, 10:54 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne updated this revision to Diff 415195.Mar 14 2022, 1:07 PM

Poke CI to try to avoid flake.

Seems reasonable to me. I left a nit, but do we also need to restore support for deduction guides in the incomplete ranges case? E.g., prior to the range constructor, we had:

template<class _Container>
    span(_Container&) -> span<typename _Container::value_type>;

template<class _Container>
    span(const _Container&) -> span<const typename _Container::value_type>;

If so, please add them back along with associated tests.

libcxx/include/span
275

Nit: I think we (mostly) use west-const everywhere, right? So, s/_Container const/const _Container/g for example.

ldionne updated this revision to Diff 415442.Mar 15 2022, 8:08 AM
ldionne marked an inline comment as done.

Address review comment and poke CI. The GCC failure was a flake.

ldionne updated this revision to Diff 415530.Mar 15 2022, 11:53 AM

Fix windows CI.

Seems reasonable to me. I left a nit, but do we also need to restore support for deduction guides in the incomplete ranges case? E.g., prior to the range constructor, we had:

template<class _Container>
    span(_Container&) -> span<typename _Container::value_type>;

template<class _Container>
    span(const _Container&) -> span<const typename _Container::value_type>;

If so, please add them back along with associated tests.

I would be tempted to say that it's OK to omit the deduction guides -- I don't expect those to have nearly as much usage, and we're breaking them slightly anyway, since we're going from Container::value_type to range_reference_t<Container> for the type stored in the span when <ranges> is implemented.

ldionne accepted this revision.Mar 15 2022, 1:34 PM

I'll ship this so I can cherry-pick it onto release/14.x ASAP.

This revision is now accepted and ready to land.Mar 15 2022, 1:34 PM