This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
transform_senderSection: 33.9.5 [exec.domain.default] Status: New Submitter: Eric Niebler Opened: 2025-08-31 Last modified: 2025-10-23
Priority: 1
View all other issues in [exec.domain.default].
View all issues with New status.
Discussion:
The following has been reported by Trevor Gray to me:
There is a potential stack-use-after-scope in
I'll give an example of the problem usingexecution::transform_senderwithexecution::default_domain::transform_sender.starts_onwith thedefault_domain.starts_ondefines atransform_sendersoexecution::transform_senderwill expand to:return transform_sender( dom, dom.transform_sender(std::forward<Sndr>(sndr), env...), env...);where
Execution flow:domis thedefault_domainandsndrisstarts_on.
dom.transform_sender(std::forward<Sndr>(sndr), env...)usesdefault_domainto invokestart_on'stransform_sender. The return type isT(whereTis alet_valuesender)
transform_sender(dom, declval<T>(), env...)is then run which usesdefault_domainto just returnstd::forward<T>(t).This means the value returned from the entire expression is
T&&which a reference to a temporary variable in the frame oftransform_senderwhich is no longer valid after the return.
In the reference implementation, this scenario does not create a dangling reference because
its implementation of default_domain::transform_sender does not conform to the spec. By default,
it returns an rvalue sender as a prvalue instead of an xvalue as the spec requires.
[2025-10-23; Reflector poll.]
Set priority to 1 after reflector poll.
"There's an NB comment to remove transform_sender entirely."
"Nothing seems to prevent Sndr from being a reference type, so I would
expect decay_t or remove_cvref_t (or decayed-typeof) instead
of the static_cast."
"I think that's intentional. The dangling happens if transform_sender is
invoked with an xvalue (where Sndr is deduced as a type). When invoked with
and lvalue (where Sndr is deduced as an lvalue reference) we don't want to
make a copy. So the static_cast makes a copy of an xvalue and not of an lvalue."
Proposed resolution:
This wording is relative to N5014.
Modify 33.9.5 [exec.domain.default] as indicated:
template<sender Sndr, queryable... Env> requires (sizeof...(Env) <= 1) constexpr sender decltype(auto) transform_sender(Sndr&& sndr, const Env&... env) noexcept(see below);-2- Let
ebe the expressiontag_of_t<Sndr>().transform_sender(std::forward<Sndr>(sndr), env...)if that expression is well-formed; otherwise,
-3- Returns:static_cast<Sndr>(std::forward<Sndr>(sndr)).e. -4- Remarks: The exception specification is equivalent tonoexcept(e).