GorNishanov / coroutines-ts

20 stars 2 forks source link

XX021: Wording of 'co_return <expr>;' statement for expressions of type void implies that <expr> is not evaluated #10

Open lewissbaker opened 7 years ago

lewissbaker commented 7 years ago

See statements.tex section on translation of co_return.

The wording currently says:

\begin{itemize}
  \item $S$ is  $p$\tcode{.return_value(}\grammarterm{braced-init-list}{}\tcode{)}, if the operand is a \grammarterm{braced-init-list};
  \item $S$ is  $p$\tcode{.return_value(}\grammarterm{expression}{}\tcode{)}, if the operand is an expression of non-\tcode{void} type;
  \item $S$ is $p$\tcode{.return_void()}, otherwise;
\end{itemize}

This wording seems to indicate that <expr> is not evaluated in co_return <expr> if the expression has type void, since <expr> does not occur in the translation. I assume this was not the intention here.

Perhaps there needs to be an extra case here to explicitly state what co_return <expr>; translates to if the type of <expr> is void? eg. insert new item between existing items 2 and 3.

\begin{itemize}
  \item $S$ is  $p$\tcode{.return_value(}\grammarterm{braced-init-list}{}\tcode{)}, if the operand is a \grammarterm{braced-init-list};
  \item $S$ is  $p$\tcode{.return_value(}\grammarterm{expression}{}\tcode{)}, if the operand is an expression of non-\tcode{void} type;
  \item $S$ is \grammarterm{expression}{}\tcode{, }$p$\tcode{.return_void()}, if the operand is an expression of \tcode{void} type;
  \item $S$ is $p$\tcode{.return_void()}, otherwise;
\end{itemize}

There may be a simpler way of wording this, however, since the 'otherwise' case now only covers co_return; without expression rather than trying to also cover co_return <void-expr>; case.

For a concrete use-case consider the following:

template<typename FUNC>
std::future<std::result_of_t<FUNC()>> run_on_thread_pool(FUNC f)
{
  co_await thread_pool::schedule();
  co_return f();
}

// Current specification says 'co_return f()' inside run_on_thread_pool()
// for this instantiation should translate to '<promise>.return_value(f());'
// since f() has non-void type. Ok, good.
std::future<int> f = run_on_thread_pool([a = 1, b = 2] { return a + b; });
assert(f.get() == 3);

// But it also says 'co_return f()' inside run_on_thread_pool() instantiation
// below should translate to '<promise>.return_void();' since f() expression
// has void type. However, this translation does not call f() which means
// the assertion would fail.
int mutableState = 0;
std::future<void> g = run_on_thread_pool([&mutableState] { mutableState = 1; });
g.wait();
assert(mutableState == 1);
GorNishanov commented 7 years ago

Thank you for the issue!

Indeed, the wording seems not cover evaluation of expression of type void. I'll capture it as an issue and bring it to core for issue resolution.

lewissbaker commented 7 years ago

I noticed in the coroutines-ts-v1.pdf that the wording was changed to { <expr>; p.return_void(); } instead of <expr>, p.return_void(); suggested in the pre-Toronto issues paper.

@GorNishanov Can you comment on the rationale for preferring destruction of temporaries in <expr> prior to p.return_void(); call rather than after the call as p.return_value(<expr>) does?

GorNishanov commented 7 years ago

This was a suggestion by the core group. The question of temporaries destructions was not voiced.

If that creates a problem we can create a defect report against the TS.

Do you have a particular case in mind where you would prefer one order over another?

From: lewissbaker [mailto:notifications@github.com] Sent: Sunday, July 30, 2017 7:55 PM To: GorNishanov/CoroutineWording CoroutineWording@noreply.github.com Cc: Gor Nishanov gorn@microsoft.com; Comment comment@noreply.github.com Subject: Re: [GorNishanov/CoroutineWording] XX021: Wording of 'co_return ;' statement for expressions of type void implies that is not evaluated (#10)

I noticed in the coroutines-ts-v1.pdf that the wording was changed to { ; p.return_void(); } instead of , p.return_void(); suggested in the pre-Toronto issues paper.

Can you comment on the rationale for preferring destruction of temporaries prior to p.return_void(); call rather than after the call as p.return_value() does?

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FGorNishanov%2FCoroutineWording%2Fissues%2F10%23issuecomment-318955151&data=04%7C01%7Cgorn%40microsoft.com%7C3f6d129e48f34a36740908d4d7bf7c33%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636370664801588936%7CUnknown%7CVW5rbm93bnx7IlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiT3RoZXIifQ%3D%3D%7C-1&sdata=u0wteBxOhZZstngzMhDZ%2BrAY6S4jWBAyez3D1nD%2FiXM%3D&reserved=0, or mute the threadhttps://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAFdx8RsIJeo7B4WlmJUEhXICY2AsIo-dks5sTUHtgaJpZM4MaKtF&data=04%7C01%7Cgorn%40microsoft.com%7C3f6d129e48f34a36740908d4d7bf7c33%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636370664801588936%7CUnknown%7CVW5rbm93bnx7IlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiT3RoZXIifQ%3D%3D%7C-1&sdata=Zf7Oe2LII4d4pFQMkAQcQt7TTc1pmNCXGgmmnbMWDPs%3D&reserved=0.

lewissbaker commented 7 years ago

I don't have a particular use-case in mind yet; every {{promise_type::return_void()}} implementation I've written so far has been trivially empty.

I was just thinking about semantics of {{return_value()}} and regular void-returning functions and what would be consistent with them.