Skip to content

Instantly share code, notes, and snippets.

@keeferrourke
Forked from theres-waldo/analysis.md
Created July 29, 2020 21:37
Show Gist options
  • Save keeferrourke/533e2061282748856cba601a031e8f95 to your computer and use it in GitHub Desktop.
Save keeferrourke/533e2061282748856cba601a031e8f95 to your computer and use it in GitHub Desktop.
C++ compiler error analysis

Starting point: mozilla-central with https://phabricator.services.mozilla.com/D85296 and dependent patches applied.

First, we make this change to trigger the error.

The relevant part of the error is:

 0:06.54 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:204:3: error: no matching function for call to 'InvokeAsync'
 0:06.54   InvokeAsync(
 0:06.54   ^~~~~~~~~~~
 0:06.54 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:281:10: note: in instantiation of function template specialization 'mozilla::dom::IOUtils::RunOnBackgroundThread<unsigned int, mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts>' requested here
 0:06.54   return RunOnBackgroundThread<uint32_t>(promise, &WriteAtomicSync, destPath,
 0:06.54          ^
 0:06.54 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/mozilla/MozPromise.h:1615:13: note: candidate template ignored: substitution failure [with Function = std::_Bind<RefPtr<mozilla::MozPromise<unsigned int, mozilla::dom::IOUtils::IOError, true> > (*(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts))(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts)>]: no matching function for call to object of type 'std::_Bind<RefPtr<mozilla::MozPromise<unsigned int, mozilla::dom::IOUtils::IOError, true> > (*(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts))(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts)>'
 0:06.54 static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
 0:06.54             ^

(I've included the first note: candidate template ignored note, since this is the InvokeAsync overload we want to call.)

Looking at InvokeAsync's signature, the substitution failure is likely happening in the decltype(aFunction()) part, but the compiler is not giving us the underlying error.

So, we make this change to form that call expression in RunOnBackgroundThread which gets the compiler to give us the reason this expression is not well-formed:

 0:06.44 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:204:3: error: no matching function for call to object of type 'typename _Bind_helper<__is_socketlike<RefPtr<MozPromise<unsigned int, IOError, true> > (&)(Result<unsigned int, IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, InternalWriteAtomicOpts)>::value, RefPtr<MozPromise<unsigned int, IOError, true> > (&)(Result<unsigned int, IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, InternalWriteAtomicOpts), Result<unsigned int, IOError> (*&)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64> &, FallibleTArray<unsigned char> &, InternalWriteAtomicOpts &>::type' (aka '_Bind<RefPtr<mozilla::MozPromise<unsigned int, mozilla::dom::IOUtils::IOError, true> > (*(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts))(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts)>')
 0:06.44   std::bind(InvokeToMozPromise<MozPromiseT, Fn, Args...>, aFunc, aArgs...)();
 0:06.44   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 0:06.45 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:282:10: note: in instantiation of function template specialization 'mozilla::dom::IOUtils::RunOnBackgroundThread<unsigned int, mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts>' requested here
 0:06.45   return RunOnBackgroundThread<uint32_t>(promise, &WriteAtomicSync, destPath,
 0:06.45          ^
 0:06.45 /home/botond/.mozbuild/clang/bin/../lib/gcc/x86_64-unknown-linux-gnu/7.4.0/../../../../include/c++/7.4.0/functional:547:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<RefPtr<mozilla::MozPromise<unsigned int, mozilla::dom::IOUtils::IOError, true> > (*&(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*&)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64> &, FallibleTArray<unsigned char> &, mozilla::dom::IOUtils::InternalWriteAtomicOpts &))(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts)>'
 0:06.45         operator()(_Args&&... __args)
 0:06.45         ^

Once again the interesting part is the first note: candidate template ignored note, which refers to the overload of the std::bind helper object's call operator that we want to call.

We see the reason this call is not valid is a substitution failure related to a std::result_of operation failing.

Unfortunately, the compiler still doesn't tell us why the std::result_of is failing.

To dig deeper, we make this change to introduce a little result_of_helper struct and a usage of it. The input type is copy-pasted from the argument to std::result_of in the previous compiler error.

Now we finally get the real error:

0:06.28 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:200:44: error: call to implicitly-deleted copy constructor of 'FallibleTArray<unsigned char>'
 0:06.28   using type = decltype(std::declval<Fn>()(std::declval<Args>()...));
 0:06.28                                            ^~~~~~~~~~~~~~~~~~~~
 0:06.29 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:214:16: note: in instantiation of template class 'mozilla::dom::result_of_helper<mozilla::dom::MozPromiseInvoker<mozilla::MozPromise<unsigned int, mozilla::dom::IOUtils::IOError, true>, mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64>, FallibleTArray<unsigned char>, mozilla::dom::IOUtils::InternalWriteAtomicOpts> &(mozilla::Result<unsigned int, mozilla::dom::IOUtils::IOError> (*&)(const nsTSubstring<char16_t> &, const FallibleTArray<unsigned char> &, const mozilla::dom::IOUtils::InternalWriteAtomicOpts &), nsTAutoStringN<char16_t, 64> &, FallibleTArray<unsigned char> &, mozilla::dom::IOUtils::InternalWriteAtomicOpts &)>' requested here
 0:06.29   using type = result_of_helper<mozilla::dom::MozPromiseInvoker<
 0:06.29                ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:2883:24: note: copy constructor of 'FallibleTArray<unsigned char>' is implicitly deleted because base class 'nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator>' has a deleted copy constructor
 0:06.29 class FallibleTArray : public nsTArray_Impl<E, nsTArrayFallibleAllocator> {
 0:06.29                        ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:1029:3: note: explicitly defaulted function was implicitly deleted here
 0:06.29   nsTArray_Impl(const nsTArray_Impl&) = default;
 0:06.29   ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:957:7: note: copy constructor of 'nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator>' is implicitly deleted because base class 'nsTArray_TypedBase<unsigned char, nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator> >' has a deleted copy constructor
 0:06.29       public nsTArray_TypedBase<E, nsTArray_Impl<E, Alloc>> {
 0:06.29       ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:820:29: note: copy constructor of 'nsTArray_TypedBase<unsigned char, nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator> >' is implicitly deleted because base class 'nsTArray_SafeElementAtHelper<unsigned char, nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator> >' has a deleted copy constructor
 0:06.29 struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper<E, Derived> {};
 0:06.29                             ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:294:39: note: copy constructor of 'nsTArray_SafeElementAtHelper<unsigned char, nsTArray_Impl<unsigned char, nsTArrayFallibleAllocator> >' is implicitly deleted because base class '::detail::nsTArray_CopyDisabler' has a deleted copy constructor
 0:06.29 struct nsTArray_SafeElementAtHelper : public ::detail::nsTArray_CopyDisabler {
 0:06.29                                       ^
 0:06.29 /home/botond/dev/projects/mozilla/central/obj-x86_64-pc-linux-gnu/dist/include/nsTArray.h:285:3: note: 'nsTArray_CopyDisabler' has been explicitly marked deleted here
 0:06.29   nsTArray_CopyDisabler(const nsTArray_CopyDisabler&) = delete;
 0:06.29   ^
 0:06.29 /home/botond/dev/projects/mozilla/central/dom/system/IOUtils.cpp:185:52: note: passing argument to parameter 'aArgs' here
 0:06.29   RefPtr<MozPromiseT> operator()(Fn aFunc, Args... aArgs) {
 0:06.29                                                    ^

This tells us the issue is that we're trying to copy a FallibleTArray which is not copyable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment