Skip to content

Commit

Permalink
Fix span for non-ranges
Browse files Browse the repository at this point in the history
We did not properly implement the short circuiting for the `__span_compatible_range` concept. So the compiler tried to instantiate `iterator_t` even for non-ranges, which obviously failed.

Fix this by properly implementing short circuiting.
  • Loading branch information
miscco committed Jun 11, 2024
1 parent e734d68 commit c73273b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
19 changes: 13 additions & 6 deletions libcudacxx/include/cuda/std/detail/libcxx/include/span
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,19 @@ _LIBCUDACXX_CONCEPT __span_array_convertible = _CCCL_TRAIT(is_convertible, _From

# if _CCCL_STD_VER >= 2017 && !defined(_CCCL_COMPILER_MSVC_2017)
template <class _Range, class _ElementType>
_LIBCUDACXX_CONCEPT __span_compatible_range =
_CUDA_VRANGES::contiguous_range<_Range> && _CUDA_VRANGES::sized_range<_Range>
&& (_CUDA_VRANGES::borrowed_range<_Range> || _CCCL_TRAIT(is_const, _ElementType))
&& !__is_std_span<remove_cvref_t<_Range>> && !__is_std_array<remove_cvref_t<_Range>>
&& !_CCCL_TRAIT(is_array, remove_cvref_t<_Range>)
&& _CCCL_TRAIT(is_convertible, remove_reference_t<_CUDA_VRANGES::range_reference_t<_Range>> (*)[], _ElementType (*)[]);
_LIBCUDACXX_CONCEPT_FRAGMENT(
__span_compatible_range_,
requires()(
requires(_CUDA_VRANGES::contiguous_range<_Range>),
requires(_CUDA_VRANGES::sized_range<_Range>),
requires((_CUDA_VRANGES::borrowed_range<_Range> || _CCCL_TRAIT(is_const, _ElementType))),
requires((!_CCCL_TRAIT(is_array, remove_cvref_t<_Range>))),
requires((!__is_std_span<remove_cvref_t<_Range>> && !__is_std_array<remove_cvref_t<_Range>>) ),
requires(_CCCL_TRAIT(
is_convertible, remove_reference_t<_CUDA_VRANGES::range_reference_t<_Range>> (*)[], _ElementType (*)[]))));

template <class _Range, class _ElementType>
_LIBCUDACXX_CONCEPT __span_compatible_range = _LIBCUDACXX_FRAGMENT(__span_compatible_range_, _Range, _ElementType);

# if _CCCL_STD_VER >= 2020
template <class _It, class _Tp>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===---------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
//
//===---------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11

// <cuda/std/span>

// Conversion from a type that is *not* a range. We had a bug where we would still try to instantiate `iterator_t`,
// which would fail because of a missing `begin`

#include <cuda/std/cassert>
#include <cuda/std/span>

#include "test_macros.h"

struct ConvertibleButNoRange
{
int buffer[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

__host__ __device__ constexpr operator cuda::std::span<int>() const noexcept
{
return cuda::std::span<int>{const_cast<int*>(buffer), 10};
}
};

__host__ __device__ constexpr bool test()
{
ConvertibleButNoRange input{};
cuda::std::span<int> converted = input;
assert(converted.data() == input.buffer);
assert(converted.size() == 10);

return true;
}

int main(int, char**)
{
test();
static_assert(test(), "");

return 0;
}

0 comments on commit c73273b

Please sign in to comment.