Created on 2025-08-31.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N5014.
Modify [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 `e` be the expression
tag_of_t<Sndr>().transform_sender(std::forward<Sndr>(sndr), env...)if that expression is well-formed; otherwise, static_cast<Sndr>(std::forward<Sndr>(sndr)).
-3- Returns: `e`. -4- Remarks: The exception specification is equivalent to `noexcept(e)`.
[ 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."
The following has been reported by Trevor Gray to me:
There is a potential stack-use-after-scope in `execution::transform_sender` with `execution::default_domain::transform_sender`.
I'll give an example of the problem using `starts_on` with the `default_domain`. `starts_on` defines a `transform_sender` so `execution::transform_sender` will expand to:return transform_sender( dom, dom.transform_sender(std::forward<Sndr>(sndr), env...), env...);where `dom` is the `default_domain` and `sndr` is `starts_on`.
Execution flow:
dom.transform_sender(std::forward<Sndr>(sndr), env...) uses `default_domain` to invoke `start_on`'s `transform_sender`. The return type is `T` (where `T` is a `let_value` sender)
transform_sender(dom, declval<T>(), env...) is then run which uses `default_domain` to just return std::forward<T>(t).
This means the value returned from the entire expression is T&& which a reference to a temporary variable in the frame of `transform_sender` which 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.
The fix is for the spec to follow suit and return prvalues when an xvalue would otherwise be returned.| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-10-23 12:39:14 | admin | set | messages: + msg15405 |
| 2025-09-15 14:55:46 | admin | set | messages: + msg15053 |
| 2025-08-31 00:00:00 | admin | create | |