libunifex icon indicating copy to clipboard operation
libunifex copied to clipboard

tag_invoke related compiler error with gcc >= 11

Open ccotter opened this issue 2 years ago • 4 comments

I was playing with the following example, and noticed it passes on GCC 10, clang 12,13,14, but fails to compile on GCC 11, 12.

    let_done(
        let_error(
                []() -> task<int> { co_return 5; }(),
            [](auto&&) noexcept { // lambda 1
                return just();
            }
        ) ,[]() noexcept { // lambda 2
            return just();
        }
    );

https://godbolt.org/z/fG6z49bM5. Note that in this example, I'm only constructing a sender, but not actually consuming (e.g. no sync_wait). I believe the error is coming from one of the is_tag_invocable evaluations, replicated below:

    auto l1 = [](auto&&) noexcept {return just(); }; // lambda 1
    auto l2 = []() noexcept { return just(); }; // lambda 2

    static_assert(
        !is_tag_invocable_v<
            _let_d::_cpo::_fn,
            _let_e::_sndr<_task::_task<int>::type, decltype(l1)>::type,
            decltype(l2)
        >);

I think the compiler seeslet_error sender's tag_invoke, eventually checking whether Receiver = unifex::_let_e::_rcvr<unifex::_task::_task<int>::type&&, main()::<lambda(auto:16&&)>, main()::<lambda()> >::type is a receiver, which it is not since main()::<lambda()> (the second lambda in my example) is not itself a receiver.

The static_assert above passes compilation on GCC 10/clang, but fails on GCC 11/12 - but fails in the same way as the original example.

Narrowing down to a smaller example

I simplified the overall code focusing on the tag_invoke portion of the code, agnostic of unifex: https://godbolt.org/z/Ee35h3eYq. This similarly passes compilation with GCC 10 and clang, but not GCC 11/12. GCC10 seems to be less eager and never attempts to instantiate receiver_type<object>, but GCC 11/12 more eagerly evaluates the template and fails the compilation while doing so. I can't tell which behavior is correct (compiler bug?).

ccotter avatar May 25 '22 03:05 ccotter

looks like this can be fixed/mitigated by checking receiver<Receiver> before sender_to<Source, SourceReceiver>, presumably gcc will short circuit before trying to instantiate the second concept evaluation.

ccotter avatar May 25 '22 17:05 ccotter

Thanks for flagging this bug with a suggested fix @ccotter. We're planning on investing more time into maintaining this library, and we've filed a task to address this bug to our backlog.

AnujYamdagni avatar Jun 29 '22 20:06 AnujYamdagni

Thanks @AnujYamdagni - I'm working through the CLA stuff with my company, but once that gets worked out I could submit a patch.

ccotter avatar Jun 30 '22 00:06 ccotter

@AnujYamdagni - would you be able to take a look at #438?

ccotter avatar Aug 10 '22 16:08 ccotter