Skip to content

Commit

Permalink
Fix indeterminate ordering in typesToValues() (#4)
Browse files Browse the repository at this point in the history
Summary:
X-link: hhvm/hhvm-staging#4

We depend on the evaluation order of the lambda passed to typesToValues() (in particular we depend on it being called for each element type in the tuple in the order in which they appear in the tuple). In C++ the order in which the values of function parameters are resolved is indeterminate:

> In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.

https://en.cppreference.com/w/cpp/language/eval_order

This diff changes `typesToValuesImpl` to use a recursive definition that should have a well-defined order.

Reviewed By: ricklavoie, alexeyt

Differential Revision: D40489955

fbshipit-source-id: 4342dde6eeda4c1002795e4f7dc2ee41c9879152
  • Loading branch information
paulbiss authored and facebook-github-bot committed Oct 19, 2022
1 parent 47fe355 commit 1174b9f
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions hphp/util/extern-worker-detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,23 @@ template <typename T> struct Tag { using Type = T; };
// for each type in that tuple. The callable is called with the tuple
// index as the first parameter, and Tag<T> as the second (where T is
// the type at that tuple index).
template <typename Tuple, typename F, size_t... Is>
template <typename Tuple, typename F, typename... Args>
auto typesToValuesImpl(F&& f,
std::index_sequence<Is...>) {
return std::make_tuple(f(Is, Tag<std::tuple_element_t<Is, Tuple>>{})...);
std::index_sequence<>,
Args&&... args) {
return std::make_tuple(std::forward<Args>(args)...);
}

template <typename Tuple, typename F, typename... Args, size_t I, size_t... Is>
auto typesToValuesImpl(F&& f,
std::index_sequence<I, Is...>,
Args&&... args) {
return typesToValuesImpl<Tuple>(
std::forward<F>(f),
std::index_sequence<Is...>{},
std::forward<Args>(args)...,
f(I, Tag<std::tuple_element_t<I, Tuple>>{})
);
}

template <typename Tuple, typename F>
Expand Down

0 comments on commit 1174b9f

Please sign in to comment.