@@ -114,32 +114,64 @@ class write_now
114114 std::stop_token token_;
115115 bool done_ = false ;
116116
117- // GCC 14 ICEs when non-trivial types live in
118- // coroutine frames; keep this wrapper trivial.
119- template <class Inner >
120- struct io_await_wrapper
117+ // GCC 14 ICEs on any template type instantiated
118+ // with an IoAwaitable in the coroutine frame, even
119+ // trivial ones. Type-erase behind function pointers
120+ // so the frame sees only a non-template struct.
121+ struct erased_io_awaiter
121122 {
122- Inner * inner_;
123+ void * inner_;
123124 promise_type* p_;
125+ bool (*ready_)(void *);
126+ coro (*suspend_)(
127+ void *, coro,
128+ executor_ref, std::stop_token);
129+ io_result<std::size_t > (*resume_)(void *);
130+ void (*destroy_)(void *);
124131
125132 bool await_ready ()
126133 {
127- return inner_-> await_ready ( );
134+ return ready_ (inner_ );
128135 }
129136
130137 coro await_suspend (coro h)
131138 {
132- return detail::call_await_suspend (
139+ return suspend_ (
133140 inner_, h,
134141 p_->ex_ , p_->token_ );
135142 }
136143
137- decltype ( auto ) await_resume()
144+ io_result<std:: size_t > await_resume ()
138145 {
139- auto r = inner_->await_resume ();
140- delete inner_;
146+ auto r = resume_ (inner_);
147+ destroy_ (inner_);
148+ inner_ = nullptr ;
141149 return r;
142150 }
151+
152+ ~erased_io_awaiter ()
153+ {
154+ if (inner_)
155+ destroy_ (inner_);
156+ }
157+
158+ erased_io_awaiter (
159+ erased_io_awaiter&& o) noexcept
160+ : inner_(std::exchange(o.inner_, nullptr ))
161+ , p_(o.p_)
162+ , ready_(o.ready_)
163+ , suspend_(o.suspend_)
164+ , resume_(o.resume_)
165+ , destroy_(o.destroy_)
166+ {
167+ }
168+
169+ erased_io_awaiter (
170+ erased_io_awaiter const &) = delete ;
171+ erased_io_awaiter& operator =(
172+ erased_io_awaiter const &) = delete ;
173+ erased_io_awaiter& operator =(
174+ erased_io_awaiter&&) = delete ;
143175 };
144176
145177 op_type get_return_object ()
@@ -207,9 +239,28 @@ class write_now
207239 if constexpr (IoAwaitable<decayed>)
208240 {
209241#if BOOST_CAPY_WRITE_NOW_WORKAROUND
210- return io_await_wrapper<decayed> {
242+ return erased_io_awaiter {
211243 new decayed (std::forward<A>(a)),
212- this };
244+ this ,
245+ +[](void * v) -> bool {
246+ return static_cast <decayed*>(
247+ v)->await_ready ();
248+ },
249+ +[](void * v, coro h,
250+ executor_ref ex,
251+ std::stop_token tok) -> coro {
252+ return detail::call_await_suspend (
253+ static_cast <decayed*>(v),
254+ h, ex, tok);
255+ },
256+ +[](void * v)
257+ -> io_result<std::size_t > {
258+ return static_cast <decayed*>(
259+ v)->await_resume ();
260+ },
261+ +[](void * v) {
262+ delete static_cast <decayed*>(v);
263+ }};
213264#else
214265 struct wrapper
215266 {
0 commit comments