Skip to content

Fix infinite recursion with debug builds on libstdc++#268

Merged
danvratil merged 1 commit intoqcoro:mainfrom
nomic-ai:fix-infinite-recursion
Mar 16, 2025
Merged

Fix infinite recursion with debug builds on libstdc++#268
danvratil merged 1 commit intoqcoro:mainfrom
nomic-ai:fix-infinite-recursion

Conversation

@cebtenzzre
Copy link
Contributor

On GCC 14.2.1 and libstdc++, during await_resume this comparison in taskbase.h:

Q_ASSERT(this->mAwaitedCoroutine != nullptr);

seems to hit an infinite recursion in std::expected here:

template<typename _Up>
  friend constexpr bool
  operator==(const expected& __x, const _Up& __v)
  // FIXME: noexcept(noexcept(bool(*__x == __v)))
  { return __x.has_value() && bool(*__x == __v); }

for this template instance:

std::operator==<std::coroutine_handle<QCoro::detail::TaskPromise<std::expected<A, B>>>>

where A and B are types used in my code.

I am not sure where the left-hand std::expected comes from, but it seems like the multiple implicit conversions that need to happen here (coroutine_handle to coroutine_handle<>, nullptr_t to coroutine_handle<>) cause sufficient ambiguity for GCC to perform the comparison in an unexpected way.

This is fixed if I change this to an implicit conversion to bool instead, as is done elsewhere in this file.

Copy link
Collaborator

@danvratil danvratil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the comparison to nullptr probably triggers some crazy chain of implicit conversions. Thanks for the fix!

@danvratil danvratil merged commit 124858b into qcoro:main Mar 16, 2025
42 checks passed
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

Successfully merging this pull request may close these issues.

2 participants