Skip to content

[libcu++] Fix __is_sequence definition for arguments framework#9271

Merged
miscco merged 2 commits into
NVIDIA:mainfrom
miscco:fix_argument_sequence_definition
Jun 9, 2026
Merged

[libcu++] Fix __is_sequence definition for arguments framework#9271
miscco merged 2 commits into
NVIDIA:mainfrom
miscco:fix_argument_sequence_definition

Conversation

@miscco

@miscco miscco commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

The current is_sequence definition is thoroughly broken. An iterator is not a sequence and neither is a pointer.

The main problem here is that this precludes passing along iterators / pointers as values which is a reasonable use case.

It also completely deviates from any standard handling in C++.

Rather than reinventing the wheel in a bad way use standard terminology to determine what is a range and what not.

A user can always wrap iterators and pointers into views and spans, so there is not need for the current definition

@miscco miscco requested a review from a team as a code owner June 5, 2026 07:17
@miscco miscco requested a review from Jacobfaib June 5, 2026 07:17
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jun 5, 2026
@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Jun 5, 2026
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Note: CodeRabbit is enabled on this repository as a convenience for maintainers
and contributors. Use your best judgment when considering its review comments and
suggestions — a suggested change may be inadequate, unnecessary, or safe to ignore.
Contributors are not expected to address every comment. Human reviews are what
ultimately matter for merging.

Overview

This PR fixes a broken sequence-detection trait used by the arguments framework. The previous element-type-based logic misclassified many types (e.g., treating tuple/complex-like types and certain wrapper-like types as sequences and preventing iterators/pointers from being passed as single values). The new definition narrows what is considered a sequence to arrays, types satisfying ranges::range, or types that provide random-access traversal. Tests were added/updated to lock in this behavior and avoid regressions.

Changes

Implementation (libcudacxx/include/cuda/__argument/argument.h)

  • Rewrote __is_sequence_v:
    • New definition: is_array_v<remove_cvref_t<_Tp>> || ranges::range<_Tp> || __has_random_access_traversal<_Tp>.
  • Removed the old element-type-based helpers (previous __is_single_value_v / __is_iterable_v logic is gone).
  • Adjusted trait defaults:
    • Primary __traits_impl<_Tp>::is_single_value behavior no longer depends on the removed helper; trait queries now reflect the new classification (pointers/iterators are treated differently by the trait).
  • Runtime validation updates:
    • __immediate::__validate_value continues to validate single-value arithmetic cases.
    • __immediate_sequence::__validate_value:
      • If __has_random_access_traversal<_Arg> is true, the random-access branch is taken (the body contains a FIXME noting that sequence size may be unknown).
      • Otherwise, if __is_sequence_v<_Arg> and the deduced element type is arithmetic, the code iterates the range and validates each element.
  • Updated static_assert text for __constant_sequence to require a “sequence” (range or array).

Tests

  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp
    • Added negative assertions that cuda::std::complex, pair, tuple, optional, expected are not sequences.
    • Confirmed wrapper-like types (range_like, element_type_like, value_type_like) are not sequences.
    • Confirmed pointers and counting_iterator are sequences when they provide random-access traversal; bidirectional iterators are not.
    • Kept C arrays, std::span, and std::array classified as sequences.
    • Updated trait expectations: e.g., __traits<int*>::is_single_value is now asserted true (reflecting the trait primary-template change).
  • libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp and static_argument.pass.cpp
    • Swapped prior __is_single_value_v assertions to use !__is_sequence_v where appropriate for unwrapped/value_type checks.
  • libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp
    • Disabled one plain-span integration test block with #if 0 and a FIXME comment (tagged FIXME(miscco)).

Rationale & Impact

  • Aligns sequence detection with standard range terminology while preserving practical handling for random-access iterators/pointers where historically accepted.
  • Prevents misclassification of tuple-like or scalar-like types (e.g., std::complex) as sequences.
  • Tests broaden negative coverage to prevent regressions.
  • Remaining concern: runtime validation for random-access iterator/pointer sequences uses a random-access path with a FIXME (size unknown). Reviewers may consider whether additional iterator-size/validation strategies, clearer documentation, or different trade-offs for treating iterators/pointers as sequences are needed.

Notes for reviewers

  • Verify the trade-off where __is_sequence_v is narrowed to ranges/arrays/random-access traversal but trait defaults were adjusted so pointer/iterator cases can still appear as single values in trait queries — ensure that matches CUB compatibility goals.
  • Consider whether the FIXME in the random-access validation path requires concrete follow-up (e.g., explicit size handling or requiring spans/views when bounds are needed).

suggestion:

Walkthrough

Reclassifies sequence detection: a sequence is now an array (after cv/ref removal), a ranges::range, or has random-access traversal; removes __is_single_value_v/__is_iterable_v; updates immediate-sequence validation, trait primary template, and tests to use __is_sequence_v (negated for single-value).

Changes

Argument type classification by ranges::range

Layer / File(s) Summary
Core implementation: sequence and traits reclassification
libcudacxx/include/cuda/__argument/argument.h
Adds iterator/ranges/array includes; redefines __is_sequence_v<_Tp> as `is_array_v<remove_cvref_t<_Tp>>
Test validation of classification changes
libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp, libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp, libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp, libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp
Adds cuda/std headers used by new assertions; updates __is_sequence_v static_asserts to mark wrapper and several cuda::std types as not sequences; preserves sequence behavior for arrays/spans and random-access pointers/iterators; replaces prior __is_single_value_v checks with !__is_sequence_v where applicable; disables one plain-span test block via #if 0 (FIXME).
  • Possibly related PRs:

    • NVIDIA/cccl#8875: Related changes to argument.h sequence/single-value trait logic.
  • Suggested reviewers:

    • ericniebler
    • gevtushenko
    • davebayer

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp

libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp:11:10: fatal error: 'cuda/_argument' file not found
11 | #include <cuda/_argument>
| ^~~~~~~~~~~~~~~~~~
1 error generated.
libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp:161:3-166:3: ERROR translating statement 'CompoundStmt'
Aborting translation of method 'test' in file 'libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Uncaught Internal Error: "Assert_failure src/clang/cAst_utils.ml:249:53"
Error backtrace:
Raised at ClangFrontend__CAst_utils.get_decl_from_typ_ptr in file "src/clang/cAst_utils.ml", line 249, characters 53-65
Called from ClangFrontend__CTrans.CTrans_funct.get_destructor_decl_ref in file "src/clang/cTrans.ml", line 658, characters 12-59
Called from ClangFrontend__CTrans.CTrans_funct.destructor_calls.(fun) in file "src/clang/cTrans.ml", line 2048, characters 12-69
Called from Base__List.rev_filter

... [truncated 2200 characters] ...

from ClangFrontend__CTrans.CTrans_funct.exec_with_node_creation in file "src/clang/cTrans.ml" (inlined), line 104, characters 20-38
Called from ClangFrontend__CTrans.CTrans_funct.get_clang_stmt_trans in file "src/clang/cTrans.ml" (inlined), line 5395, characters 4-69
Called from ClangFrontend__CTrans.CTrans_funct.get_custom_stmt_trans in file "src/clang/cTrans.ml", line 5401, characters 8-55
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs.exec_trans_instrs_rev in file "src/clang/cTrans.ml" (inlined), line 5365, characters 28-54
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs in file "src/clang/cTrans.ml" (inlined), line 5389, characters 6-70
Called from ClangFrontend__CTrans.CTrans_funct.instructions_trans in file "src/clang/cTrans.ml", line 5451, characte

libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp

libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp:11:10: fatal error: 'cuda/_argument' file not found
11 | #include <cuda/argument>
| ^~~~~~~~~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/d0863c9e28cf5d24dbe9b99d0066634a73da227c-07842b3345a172fc/tmp/clang_command_.tmp.f86dbe.txt
++Contents of '/tmp/coderabbit-infer/d0863c9e28cf5d24dbe9b99d0066634a73da227c-07842b3345a172fc/tmp/clang_command
.tmp.f86dbe.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-li

... [truncated 1169 characters] ...

al-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/07842b3345a172fc/file.o" "-x" "c++"
"libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp" "-O0"
"-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp

libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp:11:10: fatal error: 'cuda/_argument' file not found
11 | #include <cuda/_argument>
| ^~~~~~~~~~~~~~~~~~
1 error generated.
libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp:124:3-128:3: ERROR translating statement 'CompoundStmt'
Aborting translation of method 'test' in file 'libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Uncaught Internal Error: "Assert_failure src/clang/cAst_utils.ml:249:53"
Error backtrace:
Raised at ClangFrontend__CAst_utils.get_decl_from_typ_ptr in file "src/clang/cAst_utils.ml", line 249, characters 53-65
Called from ClangFrontend__CTrans.CTrans_funct.get_destructor_decl_ref in file "src/clang/cTrans.ml", line 658, characters 12-59
Called from ClangFrontend__CTrans.CTrans_funct.destructor_calls.(fun) in file "src/clang/cTrans.ml", line 2048, characters 12-69
Called from Base__List.rev_filter_ma

... [truncated 2200 characters] ...

Frontend__CTrans.CTrans_funct.get_clang_stmt_trans in file "src/clang/cTrans.ml" (inlined), line 5395, characters 4-69
Called from ClangFrontend__CTrans.CTrans_funct.get_custom_stmt_trans in file "src/clang/cTrans.ml", line 5401, characters 8-55
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs.exec_trans_instrs_rev in file "src/clang/cTrans.ml" (inlined), line 5365, characters 28-54
Called from ClangFrontend__CTrans.CTrans_funct.exec_trans_instrs in file "src/clang/cTrans.ml" (inlined), line 5389, characters 6-70
Called from ClangFrontend__CTrans.CTrans_funct.instructions_trans in file "src/clang/cTrans.ml", line 5451, characters 25-68
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.add_method.f in file "src/clang/cFrontend_decl.ml", line 48, characters 12-91

  • 1 others

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libcudacxx/include/cuda/__argument/argument.h (1)

114-114: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

important: The static_assert error messages "must have a distinct element type" are now incorrect. The new __is_sequence_v checks whether a type is an array or satisfies ranges::range, not whether it has a distinct element type. Types like element_type_like<int> have a distinct element type but are not arrays or ranges, so they would fail this check for a different reason than the message suggests.

Update the messages to reflect the actual requirement, e.g., "must be an array or range type".

Proposed fix
-  static_assert(__is_sequence_v<value_type>, "constant sequence arguments must have a distinct element type");
+  static_assert(__is_sequence_v<value_type>, "constant sequence arguments must be an array or range type");

Apply similar changes to lines 304, 701, and 714.

Also applies to: 304-304, 701-701, 714-714


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6b49057a-ad0c-4843-8771-66b0fd1e7ae9

📥 Commits

Reviewing files that changed from the base of the PR and between 2b21bec and 171cb93.

📒 Files selected for processing (4)
  • libcudacxx/include/cuda/__argument/argument.h
  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp

@miscco miscco force-pushed the fix_argument_sequence_definition branch 2 times, most recently from 90a8c02 to f13ff25 Compare June 5, 2026 07:36
@miscco

miscco commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

I have added some more tests to make sure this does not regresses again. I believe we can agree that complex<float> is not a range

@github-actions

This comment has been minimized.

inline constexpr bool __is_iterable_v<_Tp,
::cuda::std::void_t<decltype(::cuda::std::declval<const _Tp&>().begin()),
decltype(::cuda::std::declval<const _Tp&>().end())>> = true;
::cuda::std::is_array_v<::cuda::std::remove_cvref_t<_Tp>> || ::cuda::std::ranges::range<_Tp>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An array is a range though, no? Why do you need both conditionals?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not: https://godbolt.org/z/Eadh18x74

@pciolkosz

Copy link
Copy Markdown
Contributor

I am not tied to the name of this trait, but at the end of the day when user passes something that has bounds we need to understand if its one value or multiple values. We have the _sequence wrappers for that, but I wanted to provide some validation in it, this trait was supposed to answer if the thing in the wrapper looks like multiple values and what is the element type, so we can assert the values are within bounds.

I highly doubt we can convince others CUB should stop accepting iterators and pointers, so I believe we need a broader definition than just range, but maybe we can also remove the extra validation, which would remove the need for this trait. But it is likely in that case a similar trait would need to live in CUB anyway, so I am not sure if it isn't just pushing the problem to a different place

@miscco

miscco commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

I highly doubt we can convince others CUB should stop accepting iterators and pointers

We should be able to still allow pointers and iterators if that is intended, but then the check should probably be __has_random_access_traversal or similar

Also we need to then differentiate iteration over a range and iteration over an iterator. Currently the check in __validate_value only considered ranges and not iterators

The issue I have here is that a pointer / iterator does not communicate the size of the range. In a perfect world we would just pass transform_view rather than transform_iterator

Not a hill to die on definitely but I at least want to make sure that we do not consider tuple or complex as sequences

@miscco miscco force-pushed the fix_argument_sequence_definition branch from f13ff25 to c7f5b4b Compare June 8, 2026 12:46

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp (1)

85-94: ⚡ Quick win

important: Line 85 disables the plain-span scenario with #if 0, which drops coverage instead of asserting the intended rejection behavior. Replace this block with an explicit negative test (compile-fail/static assertion in the argument test suite) so the contract is enforced by CI rather than commented out.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a8f64be5-de33-471d-b9c3-6f0c1e6388d6

📥 Commits

Reviewing files that changed from the base of the PR and between c7f5b4b and ce73d17.

📒 Files selected for processing (3)
  • libcudacxx/include/cuda/__argument/argument.h
  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp

@github-actions

This comment has been minimized.

if constexpr (__is_iterable_v<_Arg> && ::cuda::std::is_arithmetic_v<__element_type>)
if constexpr (::cuda::std::__has_random_access_traversal<_Arg>)
{ // FIXME: (miscco) This is broken. we do not know the size of the sequence
__validate_element(*__arg_);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this I think we should just make validate a separate call that takes a size, but it can happen in a separate PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to merge as is, because this improves the status quo and we can handle further improvements in followup PRs

@github-actions

This comment has been minimized.

miscco added 2 commits June 9, 2026 10:59
The  current is_sequence definition is thoroughly broken. An iterator is not a sequence and neither is a pointer.

The main problem here is that this precludes passing along iterators / pointers as values which is a reasonable use case.

It also completely deviates from any standard handling in C++.

Rather than reinventing the wheel in a bad way use standard terminology to determine what is a range and what not.

A user can always wrap iterators and pointers into views and spans, so there is not need for the current definition
@miscco miscco force-pushed the fix_argument_sequence_definition branch from ce73d17 to d0863c9 Compare June 9, 2026 09:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp (1)

85-94: ⚠️ Potential issue | 🔴 Critical

suggestion: The #if 0-disabled “plain span” case leaves ambiguous FIXME intent; the argument framework enforces static_assert(__is_sequence_v<...>) only for the wrapper types (__constant_sequence / __immediate_sequence), and there’s no evidence here that an unwrapped cuda::std::span is explicitly rejected at compile time. Either remove the dead block, or turn it into a negative/positive test that matches the framework’s actual contract (unwrapped spans should be either supported and wrapped correctly, or deliberately diagnosed via an expect-error test).


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a5817848-9eb4-4794-899d-6fb322be9bb1

📥 Commits

Reviewing files that changed from the base of the PR and between ce73d17 and d0863c9.

📒 Files selected for processing (5)
  • libcudacxx/include/cuda/__argument/argument.h
  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/dynamic_argument.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp
  • libcudacxx/test/libcudacxx/cuda/argument/usage_example.pass.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • libcudacxx/test/libcudacxx/cuda/argument/static_argument.pass.cpp
  • libcudacxx/include/cuda/__argument/argument.h
  • libcudacxx/test/libcudacxx/cuda/argument/argument_traits.pass.cpp

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 38m: Pass: 100%/118 | Total: 23h 21m | Max: 55m 15s | Hits: 98%/342444

See results here.

@miscco miscco merged commit b2060aa into NVIDIA:main Jun 9, 2026
139 checks passed
@miscco miscco deleted the fix_argument_sequence_definition branch June 9, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants