Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Folly doesn't compile with Clang 8 and libc++ #1081

Closed
JoeLoser opened this issue Mar 26, 2019 · 8 comments
Closed

Folly doesn't compile with Clang 8 and libc++ #1081

JoeLoser opened this issue Mar 26, 2019 · 8 comments

Comments

@JoeLoser
Copy link
Contributor

JoeLoser commented Mar 26, 2019

With Clang 8 and libc++, so far, I have seen at least a few tests (ForeachTest.cpp line 277 and SynchronizedTest.cpp).

Stack trace for ForeachTest.cpp:

../folly/container/Foreach-inl.h:274:15: note: in instantiation of template type alias 'ForEachImplTag' requested here
  using tag = ForEachImplTag<Func, type, void>;

../folly/container/Foreach-inl.h:319:8: note: in instantiation of function template specialization 'folly::for_each_detail::for_each_impl<std::__1::tuple<folly::test::TestRValueConstruct, folly::test::TestRValueConstruct>, (lambda at ../folly/container/test/ForeachTest.cpp:277:7)>' requested here
  fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func);
       ^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4254:6: note: candidate template ignored: substitution failure [with _Args = <folly::test::TestRValueConstruct, std::__1::integral_constant<unsigned long, 0>, void>]: cannot form a reference to 'void'
auto __invoke(__any, _Args&& ...__args) -> __nat;
     ^                    ~~
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4265:1: note: candidate template ignored: substitution failure [with _Fp = (lambda at ../folly/container/test/ForeachTest.cpp:277:7), _A0 = folly::test::TestRValueConstruct, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]: no type named 'type' in 'std::__1::__member_pointer_class_type<(lambda at ../folly/container/test/ForeachTest.cpp:277:7)>'
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4279:1: note: candidate template ignored: requirement 'is_member_function_pointer<(lambda at ../folly/container/test/ForeachTest.cpp:277:7)>::value' was not satisfied [with
_Fp = (lambda at ../folly/container/test/ForeachTest.cpp:277:7), _A0 = folly::test::TestRValueConstruct, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4293:1: note: candidate template ignored: substitution failure [with _Fp = (lambda at ../folly/container/test/ForeachTest.cpp:277:7), _A0 = folly::test::TestRValueConstruct, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]: no type named 'type' in 'std::__1::__member_pointer_class_type<(lambda at ../folly/container/test/ForeachTest.cpp:277:7)>'
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4352:1: note: candidate template ignored: substitution failure [with _Fp = (lambda at ../folly/container/test/ForeachTest.cpp:277:7), _Args = <folly::test::TestRValueConstruct, std::__1::integral_constant<unsigned long, 0>, void>]: cannot form a reference to 'void'
__invoke(_Fp&& __f, _Args&& ...__args)
^                        ~~
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4309:1: note: candidate function template not viable: requires 2 arguments, but 4 were provided
__invoke(_Fp&& __f, _A0&& __a0)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4323:1: note: candidate function template not viable: requires 2 arguments, but 4 were provided
__invoke(_Fp&& __f, _A0&& __a0)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4337:1: note: candidate function template not viable: requires 2 arguments, but 4 were provided
__invoke(_Fp&& __f, _A0&& __a0)
^
In file included from ../folly/container/test/ForeachTest.cpp:17:
In file included from ../folly/container/Foreach.h:255:
../folly/container/Foreach-inl.h:276:3: error: no matching function for call to 'for_each_tuple_impl'
  for_each_tuple_impl(tag{}, std::forward<Sequence>(range), func);
  ^~~~~~~~~~~~~~~~~~~
../folly/container/Foreach-inl.h:319:8: note: in instantiation of function template specialization 'folly::for_each_detail::for_each_impl<std::__1::tuple<folly::test::TestRValueConstruct, folly::test::TestRValueConstruct>, (lambda at ../folly/container/test/ForeachTest.cpp:277:7)>' requested here
  fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func);
       ^
../folly/container/Foreach-inl.h:244:6: note: candidate function template not viable: no known conversion from 'tag' (aka 'int') to 'index_constant<2>' (aka 'integral_constant<unsigned long, 2UL>') for 1st argument
void for_each_tuple_impl(index_constant<2>, Sequence&& seq, Func& func) {
     ^
../folly/container/Foreach-inl.h:254:6: note: candidate function template not viable: no known conversion from 'tag' (aka 'int') to 'index_constant<1>' (aka 'integral_constant<unsigned long, 1UL>') for 1st argument
void for_each_tuple_impl(index_constant<1>, Sequence&& seq, Func& func) {
     ^
../folly/container/Foreach-inl.h:209:6: note: candidate template ignored: could not match 'integer_sequence<unsigned long, Indices...>' against 'int'
void for_each_tuple_impl(
     ^

SynchronizedTest.cpp stack trace:

In file included from ../folly/test/SynchronizedTest.cpp:20:
In file included from ../folly/Synchronized.h:27:
In file included from ../folly/Function.h:220:
In file included from /usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/functional:491:
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4371:9: error: no matching function for call to '__invoke'
        _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
        ^~~~~~~~~~~~~~~
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/__config:816:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
              ^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4465:31: note: in instantiation of template class 'std::__1::__invokable_r<void, (lambda at ../folly/Synchronized.h:936:23), folly::detail::SynchronizedLocker<const folly::S
ynchronized<int, folly::(anonymous namespace)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &, std::__1::integral_constant<unsigned long, 0>, void>' requested here
    : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
                              ^
../folly/container/Foreach-inl.h:136:5: note: in instantiation of template class 'std::__1::is_invocable<(lambda at ../folly/Synchronized.h:936:23), folly::detail::SynchronizedLocker<const folly::Synchronized<int, folly::(anonymous name
space)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &, std::__1::integral_constant<unsigned long, 0>, void>' requested here
    is_invocable<Func, Item, index_constant<0>, Iter>::value,
    ^
../folly/container/Foreach-inl.h:274:15: note: in instantiation of template type alias 'ForEachImplTag' requested here
  using tag = ForEachImplTag<Func, type, void>;
              ^
../folly/container/Foreach-inl.h:319:8: note: in instantiation of function template specialization 'folly::for_each_detail::for_each_impl<std::__1::tuple<folly::detail::SynchronizedLocker<const folly::Synchronized<int, folly::(anonymous
 namespace)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &> &, (lambda at ../folly/Synchronized.h:936:23)>' requested here
  fed::for_each_impl(tag{}, std::forward<Sequence>(sequence), func);
       ^
../folly/Synchronized.h:1643:7: note: in instantiation of function template specialization 'folly::detail::lock<folly::detail::SynchronizedLocker<const folly::Synchronized<int, folly::(anonymous namespace)::TestSharedMutex>, (lambda at
../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> >' requested here
      lock(std::forward<SynchronizedLockers>(lockers)...));
      ^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4254:6: note: candidate template ignored: substitution failure [with _Args = <folly::detail::SynchronizedLocker<const folly::Synchronized<int, folly::(anonymous namespace)::
TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &, std::__1::integral_constant<unsigned long, 0>, void>]: cannot form a reference to 'void'
auto __invoke(__any, _Args&& ...__args) -> __nat;
     ^                    ~~
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4265:1: note: candidate template ignored: substitution failure [with _Fp = (lambda at ../folly/Synchronized.h:936:23), _A0 = folly::detail::SynchronizedLocker<const folly::S
ynchronized<int, folly::(anonymous namespace)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]: no type named 'typ
e' in 'std::__1::__member_pointer_class_type<(lambda at ../folly/Synchronized.h:936:23)>'
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4279:1: note: candidate template ignored: requirement 'is_member_function_pointer<(lambda at ../folly/Synchronized.h:936:23)>::value' was not satisfied [with _Fp = (lambda a
t ../folly/Synchronized.h:936:23), _A0 = folly::detail::SynchronizedLocker<const folly::Synchronized<int, folly::(anonymous namespace)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:
7)> &, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)
^
/usr/local/Cellar/llvm/8.0.0/bin/../include/c++/v1/type_traits:4293:1: note: candidate template ignored: substitution failure [with _Fp = (lambda at ../folly/Synchronized.h:936:23), _A0 = folly::detail::SynchronizedLocker<const folly::S
ynchronized<int, folly::(anonymous namespace)::TestSharedMutex>, (lambda at ../folly/Synchronized.h:988:7), (lambda at ../folly/Synchronized.h:991:7)> &, _Args = <std::__1::integral_constant<unsigned long, 0>, void>]: no type named 'typ
e' in 'std::__1::__member_pointer_class_type<(lambda at ../folly/Synchronized.h:936:23)>'
__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args)

I have a small patch for folly/test/SingletonTestStructs.h which fails due to

../folly/test/SingletonTestStructs.h:46:13: error: explicitly defaulted move assignment operator is implicitly deleted [-Werror,-Wdefaulted-function-deleted]
  Watchdog& operator=(Watchdog&&) noexcept = default;
            ^
../folly/test/SingletonTestStructs.h:38:16: note: move assignment operator of 'Watchdog' is implicitly deleted because field 'serial_number' is of const-qualified type 'const size_t' (aka 'const unsigned long')
  const size_t serial_number;
               ^
1 error generated.
JoeLoser added a commit to JoeLoser/folly that referenced this issue Mar 26, 2019
Summary:
- Clang 8 introduces a new compiler option which is turned on by
  default: `-Wdefaulted-function-deleted`.
- This flags some code which has special member functions which we
  declare as defaulted, but are implicitly deleted. As such, it is a bit
  misleading to mark them as defaulted. So, mark them as deleted. We
  could also remove them and they would be implicitly deleted, but then
  the internal linter would not like that we define a user defined type
  but are not explicit about deleting or defaulting all special member
  functions.

Note:
- This fixes some Clang 8 compilation issues, but
  facebook#1081 contains details about the
  remaining issues.
facebook-github-bot pushed a commit that referenced this issue Mar 26, 2019
Summary:
- Clang 8 introduces a new compiler option which is turned on by
  default: `-Wdefaulted-function-deleted`.
- This flags some code which has special member functions which we
  declare as defaulted, but are implicitly deleted. As such, it is a bit
  misleading to mark them as defaulted. So, mark them as deleted. We
  could also remove them and they would be implicitly deleted, but then
  the internal linter would not like that we define a user defined type
  but are not explicit about deleting or defaulting all special member
  functions.

Note:
- This fixes some Clang 8 compilation issues, but
  #1081 contains details about the
  remaining issues.
Pull Request resolved: #1082

Reviewed By: Orvid

Differential Revision: D14613574

Pulled By: yfeldblum

fbshipit-source-id: 8011b3bc456bf92bbaf374c045fffb130e26d38b
@JoeLoser
Copy link
Contributor Author

JoeLoser commented May 6, 2019

@yfeldblum @Orvid has anyone looked at the remaining Clang 8 compilation issues? It's not obvious to me what the issue(s) are.

@yfeldblum
Copy link
Contributor

I haven't seen these internally. Are these build failures related to using libc++ (clang's c++ std lib) instead of libstdc++ (gcc's c++ std lib)?

@JoeLoser
Copy link
Contributor Author

JoeLoser commented May 7, 2019

I have only tried with clang 8 and libc++. Since internally I believe you're using clang 8 with libstdc++, it's likely a libcpp issue.

Are you able to reproduce it internally when using libc++?

@yfeldblum
Copy link
Contributor

I haven't tried with libc++.

Betting this is related: https://godbolt.org/z/_8vhHg. Possibly libc++'s std::invoke doesn't handle void args quite like libstdc++'s in some unknown magical way. Relevant to the definition of ForEachImplTag, which is using folly::is_invocable which looks like it should be using folly::invoke, but which is using std::invoke because one of the arguments is std::integral_constant.

@JoeLoser JoeLoser changed the title Folly doesn't compile with Clang 8 Folly doesn't compile with Clang 8 and libc++ May 16, 2019
@JoeLoser
Copy link
Contributor Author

I think you're definitely on the right track with the handling of the void arg. When we change Invoke.h to always use the backported invoke rather than std::invoke for Clang 8 with libc++, we run into SFINAE errors in invokeForward (which is SFINAEing on whether the invoke call is well-formed). This seems different than the trying to form reference to void.

[449/617] Building CXX object CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o
FAILED: CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o
/usr/local/Cellar/llvm/8.0.0/bin/clang++  -DFOLLY_XLOG_STRIP_PREFIXES=\"/Users/joe/dev/folly:/Users/joe/dev/folly/_build\" -DGFLAGS_IS_A_DLL=0 -D_GNU_SOURCE -D_REENTRANT -I../ -I. -I/usr/local/boost-1.68.0/include -I/usr/local/Cellar/openssl/1.0.2r/include -isystem /usr/local/include -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk   -g -std=gnu++1z -finput-charset=UTF-8 -fsigned-char -Wall -Wno-deprecated -Wno-deprecated-declarations -Wno-sign-compare -Wno-unused -Wunused-label -Wunused-result -Wno-noexcept-type -Wno-nullability-completeness -Wno-inconsistent-missing-override -faligned-new -fopenmp -MD -MT CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o -MF CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o.d -o CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o -c ../folly/functional/test/PartialTest.cpp
../folly/functional/test/PartialTest.cpp:129:17: error: no matching function for call to object of type 'typename remove_reference<Partial<unique_ptr<int, default_delete<int> > (*)(unique_ptr<int, default_delete<int> >, unique_ptr<int,
default_delete<int> >), tuple<unique_ptr<int, default_delete<int> > > > &>::type' (aka 'folly::detail::partial::Partial<std::__1::unique_ptr<int, std::__1::default_delete<int> > (*)(std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::unique_ptr<int, std::__1::default_delete<int> >), std::__1::tuple<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >')
  auto result = std::move(p)(std::move(six));
                ^~~~~~~~~~~~
../folly/functional/Partial.h:58:8: note: candidate function template not viable: no known conversion from 'Partial<...>' to 'Partial<...>' for object argument
  auto operator()(CArgs&&... cargs) & -> decltype(invokeForward(
       ^
../folly/functional/Partial.h:65:8: note: candidate template ignored: substitution failure [with CArgs = <std::__1::unique_ptr<int, std::__1::default_delete<int> >>]: use of undeclared identifier 'invokeForward'
  auto operator()(CArgs&&... cargs) const& -> decltype(invokeForward(
       ^                                               ~~~~~~~~~~~~~
../folly/functional/Partial.h:72:8: note: candidate template ignored: substitution failure [with As = <std::__1::unique_ptr<int, std::__1::default_delete<int> >>]: use of undeclared identifier 'invokeForward'
  auto operator()(As&&... a) && -> decltype(invokeForward(
       ^                                    ~~~~~~~~~~~~~
../folly/functional/Partial.h:79:8: note: candidate template ignored: substitution failure [with As = <std::__1::unique_ptr<int, std::__1::default_delete<int> >>]: use of undeclared identifier 'invokeForward'
  auto operator()(As&&... as) const&& -> decltype(invokeForward(
       ^                                          ~~~~~~~~~~~~~

@JoeLoser
Copy link
Contributor Author

I would expect this to be fixed with llvm-mirror/libcxx@a32a775#diff-48f5ee43879b5ad38888f0a6ead10113

Your example doesn't quite work, but the ones below should:
https://wandbox.org/permlink/p0nTOwhj13P6gqyL -> shows failure with Clang 8 and -stdlib=libc++
https://wandbox.org/permlink/8gOgOAF6jqDEuR1V -> shows success with Clang trunk and -stdlib=libc++

I'll check if the Folly code builds fine tomorrow with Clang trunk and libc++ and circle back.

@JoeLoser
Copy link
Contributor Author

JoeLoser commented Jun 2, 2019

Folly builds fine when I use libc++ trunk, proving this was a libc++ quirk compared to libstdc++.

In my opinion, it is probably not worth designing a workaround which would only be for Clang 8 and libc++ considering Clang 8.0.1 will come out not too far from now. This issue does not arise when using Clang 7 and libc++.

In any regard, closing this issue.

@JoeLoser JoeLoser closed this as completed Jun 2, 2019
facebook-github-bot pushed a commit that referenced this issue Dec 4, 2024
Summary: Pull Request resolved: facebookincubator/zstrong#1081

Reviewed By: bigfootjon

Differential Revision: D66702321

fbshipit-source-id: 6b16249fb48357a452d82067fb6a468b5d10bc13
@Dragonfly5596
Copy link

[449/617] Building CXX object CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o
FAILED: CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o
/usr/local/Cellar/llvm/8.0.0/bin/clang++ -DFOLLY_XLOG_STRIP_PREFIXES="/Users/joe/dev/folly:/Users/joe/dev/folly/_build" -DGFLAGS_IS_A_DLL=0 -D_GNU_SOURCE -D_REENTRANT -I../ -I. -I/usr/local/boost-1.68.0/include -I/usr/local/Cellar/openssl/1.0.2r/include -isystem /usr/local/include -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -g -std=gnu++1z -finput-charset=UTF-8 -fsigned-char -Wall -Wno-deprecated -Wno-deprecated-declarations -Wno-sign-compare -Wno-unused -Wunused-label -Wunused-result -Wno-noexcept-type -Wno-nullability-completeness -Wno-inconsistent-missing-override -faligned-new -fopenmp -MD -MT CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o -MF CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o.d -o CMakeFiles/partial_test.dir/folly/functional/test/PartialTest.cpp.o -c ../folly/functional/test/PartialTest.cpp
../folly/functional/test/PartialTest.cpp:129:17: error: no matching function for call to object of type 'typename remove_reference<Partial<unique_ptr<int, default_delete > ()(unique_ptr<int, default_delete >, unique_ptr<int,
default_delete >), tuple<unique_ptr<int, default_delete > > > &>::type' (aka 'folly::detail::partial::Partial<std::__1::unique_ptr<int, std::__1::default_delete > (
)(std::__1::unique_ptr<int, std::__1::default_delete >, std::__1::unique_ptr<int, std::__1::default_delete >), std::__1::tuple<std::__1::unique_ptr<int, std::__1::default_delete > > >')
auto result = std::move(p)(std::move(six));
^~~~~~~~~~~~
../folly/functional/Partial.h:58:8: note: candidate function template not viable: no known conversion from 'Partial<...>' to 'Partial<...>' for object argument
auto operator()(CArgs&&... cargs) & -> decltype(invokeForward(
^
../folly/functional/Partial.h:65:8: note: candidate template ignored: substitution failure [with CArgs = <std::__1::unique_ptr<int, std::__1::default_delete >>]: use of undeclared identifier 'invokeForward'
auto operator()(CArgs&&... cargs) const& -> decltype(invokeForward(
^ ~~~~~~~~~~~~~
../folly/functional/Partial.h:72:8: note: candidate template ignored: substitution failure [with As = <std::__1::unique_ptr<int, std::__1::default_delete >>]: use of undeclared identifier 'invokeForward'
auto operator()(As&&... a) && -> decltype(invokeForward(
^ ~~~~~~~~~~~~~
../folly/functional/Partial.h:79:8: note: candidate template ignored: substitution failure [with As = <std::__1::unique_ptr<int, std::__1::default_delete >>]: use of undeclared identifier 'invokeForward'
auto operator()(As&&... as) const&& -> decltype(invokeForward(
^ ~~~~~~~~~~~~~acre

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants