[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 Michael Bruck changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |INVALID --- Comment #8 from Michael Bruck --- Yes. Also std::is_lambda_closure<> or an equivalent facility seems to be missing from the std.
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #7 from Iain Sandoe --- to summarise. This doesn't appear to be a bug in GCC (or clang) but something perhaps that could benefit from a clarifying note in the std?
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #6 from Iain Sandoe --- (In reply to Michael Bruck from comment #5) > > Since the coroutine traits are global, and the closure type is unique, > > that provides a way to disambiguate instantiations of the traits for > > lambdas with otherwise identical signatures. > > But the closure type is generated in the same lambda expression where the > coroutine generator looks up the coroutine_traits<>. How do I specialize on > that? I wasn't meaning to suggest you can specialise per lambda (but I was saying that the traits instantiated will be unique per lambda) - perhaps the latter is an implementation detail. Providing the class/callable object type to the traits look does allow specialisations like ... template struct std::coroutine_traits { struct promise_type { promise_type (CallOp op, T ...args) {} Fake get_return_object() { return {}; } std::suspend_always initial_suspend() { return {}; } to be possible. ( I might be getting out of my depth with the long history of the design evolution here - but this is my understanding of the rationale for the status quo ).
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #5 from Michael Bruck --- > Since the coroutine traits are global, and the closure type is unique, > that provides a way to disambiguate instantiations of the traits for > lambdas with otherwise identical signatures. But the closure type is generated in the same lambda expression where the coroutine generator looks up the coroutine_traits<>. How do I specialize on that?
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #4 from Iain Sandoe --- (In reply to Michael Bruck from comment #3) > I think you misread, I was complaining about it passing the closure to the > traits/constructor/allocator. But if that is what was agreed upon... > > Can the closure object that is being passed to the constructor and allocator > be used for anything? I am asking because I got it to pass nullptr with the > code below. But if there is no legitimate use it might as well always pass a > nullptr. OK.. I think I did misread (I was under the impression you wanted better diagnostics for the case where the user had intentionally specialised the traits - but made an error). [FTR, I am not sure if that's feasible - but someone with more specialisation-fu can comment on that]. --- I think we need the closure object type in the traits lookup because: Since the coroutine traits are global, and the closure type is unique, that provides a way to disambiguate instantiations of the traits for lambdas with otherwise identical signatures. The callable is usable in the other positions - I don't think that was particularly in debate. The issue was about whether we should pass a reference to the closure or the pointer (and it was decided that symmetry with the class object that a reference was the intention). The fix is not yet in master (to make it a reference) - it's pending review (but you could apply it to test things out).
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #3 from Michael Bruck --- I think you misread, I was complaining about it passing the closure to the traits/constructor/allocator. But if that is what was agreed upon... Can the closure object that is being passed to the constructor and allocator be used for anything? I am asking because I got it to pass nullptr with the code below. But if there is no legitimate use it might as well always pass a nullptr. template struct foo_t { static auto test() { return F(); } }; using moo = foo_t<[]() -> pt::handle_t{ co_return; }>; ... int main { moo::test(); }
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 Iain Sandoe changed: What|Removed |Added Status|UNCONFIRMED |NEW Ever confirmed|0 |1 Assignee|unassigned at gcc dot gnu.org |iains at gcc dot gnu.org Target Milestone|--- |10.2 Last reconfirmed||2020-06-05 --- Comment #2 from Iain Sandoe --- There was a long discussion amongst the implementors at WG21 meeting in Prague about what should be done for the closure object. The standard is really silent about coroutines and lambdas except by inference (and different implementors had made different inferences). The end result of the discussion is that we should treat it the same way as a class object (passing a reference to it to the traits, allocator lookup and promise parameter preview). current MSVC is the only implementation to have this complete, clang passes the reference to the traits but not to the allocator / promise. GCC (current code) passes the closure pointer to all three. I posted a patch here: https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546299.html to bring GCC up to date with the agreed interpretation. After that, diagnostics will (as ever) be a QoI issue - as far as coroutines go, the implementation makes use of the same lookup facilities as the rest of the C++ FE (so we should expect a consistent behaviour in terms of diagnostics). (libraries like cppcoro etc. make heavy use of coroutine lambdas, so they are certainly found to be viable).
[Bug c++/95540] [coroutine] coroutine_traits<> lookup for lambdas
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95540 --- Comment #1 from Michael Bruck --- "impossible" is too strong here, you can add another overload: template struct std::coroutine_traits { using promise_type = pt; };