Skip to content

Conversation

@Aminsed
Copy link
Contributor

@Aminsed Aminsed commented Nov 23, 2025

Summary

  • reuse the existing extended-lambda detection logic from invoke_result to block is_invocable{,_r} and is_nothrow_invocable{,_r} when host builds introspect extended lambdas
  • rely on a shared helper so the diagnostic is consistent for both __device__ and __host__ __device__ closures
  • add NVCC-only .fail.cpp tests that instantiate each trait with extended lambdas to prove the static assertions fire

Testing

  • ./ci/util/build_and_test_targets.sh --preset libcudacxx-cpp20 --cmake-options "-DCMAKE_CUDA_HOST_COMPILER=/usr/bin/g++ -DCMAKE_CXX_COMPILER=/usr/bin/g++" --lit-tests "std/utilities/meta/meta.rel/is_invocable.extended_device_lambda.fail.cpp std/utilities/meta/meta.rel/is_invocable.extended_host_device_lambda.fail.cpp std/utilities/meta/meta.rel/is_nothrow_invocable.extended_device_lambda.fail.cpp"
  • pre-commit run --files libcudacxx/include/cuda/std/__functional/invoke.h libcudacxx/test/libcudacxx/std/utilities/meta/meta.rel/is_invocable.extended_device_lambda.fail.cpp libcudacxx/test/libcudacxx/std/utilities/meta/meta.rel/is_invocable.extended_host_device_lambda.fail.cpp libcudacxx/test/libcudacxx/std/utilities/meta/meta.rel/is_nothrow_invocable.extended_device_lambda.fail.cpp

Fixes #1984.

@Aminsed Aminsed requested a review from a team as a code owner November 23, 2025 05:58
@Aminsed Aminsed requested a review from pciolkosz November 23, 2025 05:58
@github-project-automation github-project-automation bot moved this to Todo in CCCL Nov 23, 2025
@copy-pr-bot
Copy link
Contributor

copy-pr-bot bot commented Nov 23, 2025

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app bot moved this from Todo to In Review in CCCL Nov 23, 2025
@Aminsed Aminsed force-pushed the feature/libcudacxx-invocability-guards branch 2 times, most recently from b1c2267 to 70491f3 Compare November 23, 2025 06:03
@Aminsed Aminsed force-pushed the feature/libcudacxx-invocability-guards branch from 70491f3 to 150d8f6 Compare November 23, 2025 06:06
Copy link
Contributor

@miscco miscco left a comment

Choose a reason for hiding this comment

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

I believe it is not correct to add those checks in the generic is_invocable machinery

As the error message points out we need this check in places where we need to query the return type of the invokable.

This is already done in the invoke_result struct above is_invocable

If we only want to invoke the lambda, there is no reason to error out. This is especially true, given that this is a nontrivial source breaking change.

@github-project-automation github-project-automation bot moved this from In Review to In Progress in CCCL Nov 24, 2025
static_assert(!__detail::__disallow_extended_lambda_invocability_v<_Fn>,
"Attempt to use an extended __device__ or __host__ __device__ lambda in a context "
"that requires querying its invocability in host code. Use a named function object or "
"cuda::proclaim_return_type instead.");
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we shouldn't mention cuda::proclaim_return_type, because it won't help here

@pciolkosz
Copy link
Contributor

pciolkosz commented Nov 25, 2025

If we only want to invoke the lambda, there is no reason to error out. This is especially true, given that this is a nontrivial source breaking change.

I don't agree. I had a use case like this:

if constexpr (is_invocable<Fn, Args...>) {
   // call Fn
}
else {
   // do something else
}

There is no way to express that with invoke_result and currently if Fn is an extended lambda the if statement always evaluates to true regardless of what the argument types are, leading to errors. It might lead to missed errors if someone is not aware of this bizarre behavior.

The source breaking is a valid point, but in the case we would error out we return a false result, which I would say is even worse

@miscco
Copy link
Contributor

miscco commented Nov 25, 2025

The source breaking is a valid point, but in the case we would error out we return a false result, which I would say is even worse

If you care about the return type you need to query it through is_invocable_r and not break other users that dont

Address miscco's feedback: keep diagnostics only in invoke_result
where the return type is actually queried. The plain is_invocable
traits should remain usable for SFINAE without breaking existing code.
@Aminsed
Copy link
Contributor Author

Aminsed commented Nov 30, 2025

@miscco Thanks for the feedback. I've removed the static_asserts from the invocability traits and kept the diagnostic only in invoke_result where the return type is actually queried. Please let me know if there's anything else that needs adjustment.

@Aminsed Aminsed requested a review from miscco November 30, 2025 02:54
Copy link
Contributor

@miscco miscco left a comment

Choose a reason for hiding this comment

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

These changes are actually pessimizations of the current code.

We do not want to instantiate types just to access a value that we could have gotten directly.

I believe we should close this

Comment on lines -246 to -252
template <class _Fp, class... _Args>
inline constexpr bool is_nothrow_invocable_v =
__nothrow_invocable_r_imp<__is_invocable<_Fp, _Args...>, true, void, _Fp, _Args...>;
template <class _Ret, class _Fp, class... _Args>
inline constexpr bool is_nothrow_invocable_r_v =
__nothrow_invocable_r_imp<__is_invocable_r<_Ret, _Fp, _Args...>, is_void_v<_Ret>, _Ret, _Fp, _Args...>;
Copy link
Contributor

Choose a reason for hiding this comment

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

This is actually really bad because it now forces us to instantiate types when we do not want to do that

@Aminsed Aminsed closed this Nov 30, 2025
@github-project-automation github-project-automation bot moved this from In Progress to Done in CCCL Nov 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[FEA]: Consider adding a static_assert to cuda::std::is_invocable that fails where its used in host code on an extended lambda

3 participants