recursive function
Summary:
Check that recursion builds with specific versions of gcc. Fix failures with that version.
Addresses these failures:
```
In file included from folly/test/FunctionTest.cpp:17:
folly/Function.h: In substitution of 'template<class ReturnType, class ... Args> template<class F, class R> using IfSafeResult = folly::detail::function::IfSafeResultImpl<R, ReturnType> [with F = folly::Function<RecFolly()>; R = RecFolly; ReturnType = RecFolly; Args = {}]':
folly/Function.h:761:7: required by substitution of 'template<class Signature, class> folly::Function<RecFolly()>::Function(folly::Function<F>&&) [with Signature = RecFolly(); <template-parameter-1-2> = <missing>]'
folly/Function.h:293:40: required by substitution of 'template<class From, class To, class> using IfSafeResultImpl = decltype ((void)(static_cast<To>(declval<From>()))) [with From = RecFolly; To = RecFolly; <template-parameter-1-3> = void]'
folly/Function.h:363:9: required by substitution of 'template<class ReturnType, class ... Args> template<class F, class R> using IfSafeResult = folly::detail::function::IfSafeResultImpl<R, ReturnType> [with F = folly::Function<RecFolly()>; R = RecFolly; ReturnType = RecFolly; Args = {}]'
folly/Function.h:761:7: required by substitution of 'template<class Signature, class> folly::Function<RecFolly()>::Function(folly::Function<F>&&) [with Signature = RecFolly(); <template-parameter-1-2> = <missing>]'
folly/Function.h:293:40: required by substitution of 'template<class From, class To, class> using IfSafeResultImpl = decltype ((void)(static_cast<To>(declval<From>()))) [with From = RecFolly; To = RecFolly; <template-parameter-1-3> = void]'
folly/Function.h:363:9: [ skipping 501 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
folly/Function.h:363:9: required by substitution of 'template<class ReturnType, class ... Args> template<class F, class R> using IfSafeResult = folly::detail::function::IfSafeResultImpl<R, ReturnType> [with F = folly::Function<RecFolly()>; R = RecFolly; ReturnType = RecFolly; Args = {}]'
folly/Function.h:761:7: required by substitution of 'template<class Signature, class> folly::Function<RecFolly()>::Function(folly::Function<F>&&) [with Signature = RecFolly(); <template-parameter-1-2> = <missing>]'
folly/Function.h:293:40: required by substitution of 'template<class From, class To, class> using IfSafeResultImpl = decltype ((void)(static_cast<To>(declval<From>()))) [with From = RecFolly; To = RecFolly; <template-parameter-1-3> = void]'
folly/Function.h:363:9: required by substitution of 'template<class ReturnType, class ... Args> template<class F, class R> using IfSafeResult = folly::detail::function::IfSafeResultImpl<R, ReturnType> [with F = folly::Function<RecFolly()>; R = RecFolly; ReturnType = RecFolly; Args = {}]'
folly/Function.h:761:7: required by substitution of 'template<class Signature, class> folly::Function<RecFolly()>::Function(folly::Function<F>&&) [with Signature = RecFolly(); <template-parameter-1-2> = <missing>]'
folly/test/FunctionTest.cpp:212:54: required from here
folly/Function.h:363:9: fatal error: template instantiation depth exceeds maximum of 512 (use '-ftemplate-depth=' to increase the maximum)
363 | using IfSafeResult = IfSafeResultImpl<R, ReturnType>;
| ^~~~~~~~~~~~
compilation terminated.
```
```
In file included from folly/test/FunctionTest.cpp:17:
folly/Function.h: In member function 'virtual void Function_SelfMove_Test::TestBody()':
folly/Function.h:709:70: error: 'f.folly::Function<int()>::exec_' is used uninitialized in this function [-Werror=uninitialized]
709 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
| ~~~~~^~~~~
folly/Function.h: In member function 'virtual void Function_SelfMove2_Test::TestBody()':
folly/Function.h:709:70: warning: 'f.folly::Function<int()>::exec_' may be used uninitialized in this function [-Wmaybe-uninitialized]
709 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
| ~~~~~^~~~~
folly/Function.h: In member function 'virtual void Function_SelfStdSwap_Test::TestBody()':
folly/Function.h:709:70: error: 'f.folly::Function<int()>::exec_' is used uninitialized in this function [-Werror=uninitialized]
709 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
| ~~~~~^~~~~
folly/Function.h:709:70: warning: 'f.folly::Function<int()>::exec_' may be used uninitialized in this function [-Wmaybe-uninitialized]
709 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
| ~~~~~^~~~~
folly/Function.h:709:70: warning: 'f.folly::Function<int()>::exec_' may be used uninitialized in this function [-Wmaybe-uninitialized]
709 | Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
| ~~~~~^~~~~
```
Notes:
* For some versions of gcc, the compiler sees the converting-move-ctor as a better match than the actual move-ctor and this leads the compiler to infinite recursion; to work around this, explicitly exclude the same-type case of the converting-move-ctor.
* `std::exchange` on `exec_` would be incorrect for self-move because of order of operations.
* `std::exchange` on `call_` might be correct but it would be an extra template instantiation which is not desireable for `folly::Function`.
Differential Revision: D33881266
fbshipit-source-id: 5403b83498b9c1afa772564246eba4f112495761
Showing
Please register or sign in to comment