<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2025-05-16" />
  <title>High-Quality Sender Diagnostics with Constexpr
Exceptions</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">High-Quality Sender
Diagnostics with Constexpr Exceptions</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3557R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-05-16</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LWG Library Working Group<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Eric Niebler<br>&lt;<a href="mailto:eric.niebler@gmail.com" class="email">eric.niebler@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#executive-summary" id="toc-executive-summary"><span class="toc-section-number">2</span> Executive
Summary<span></span></a></li>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">3</span> Revision History<span></span></a>
<ul>
<li><a href="#r2" id="toc-r2"><span class="toc-section-number">3.1</span> R2<span></span></a></li>
<li><a href="#r1" id="toc-r1"><span class="toc-section-number">3.2</span> R1<span></span></a></li>
<li><a href="#r0" id="toc-r0"><span class="toc-section-number">3.3</span> R0<span></span></a></li>
</ul></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">4</span> Motivation<span></span></a>
<ul>
<li><a href="#example" id="toc-example"><span class="toc-section-number">4.1</span> Example<span></span></a>
<ul>
<li><a href="#with-constexpr-exceptions" id="toc-with-constexpr-exceptions"><span class="toc-section-number">4.1.1</span> With
<code class="sourceCode default">constexpr</code>
exceptions:<span></span></a></li>
<li><a href="#without-constexpr-exceptions" id="toc-without-constexpr-exceptions"><span class="toc-section-number">4.1.2</span> Without
<code class="sourceCode default">constexpr</code>
exceptions:<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#proposed-design" id="toc-proposed-design"><span class="toc-section-number">5</span> Proposed Design<span></span></a>
<ul>
<li><a href="#get_completion_signatures" id="toc-get_completion_signatures"><span class="toc-section-number">5.1</span>
<code class="sourceCode default">get_completion_signatures</code><span></span></a>
<ul>
<li><a href="#non-non-dependent-senders" id="toc-non-non-dependent-senders"><span class="toc-section-number">5.1.1</span> <em>Non</em>-non-dependent
senders<span></span></a></li>
<li><a href="#implementation" id="toc-implementation"><span class="toc-section-number">5.1.2</span>
Implementation<span></span></a></li>
</ul></li>
<li><a href="#sender_in" id="toc-sender_in"><span class="toc-section-number">5.2</span>
<code class="sourceCode default">sender_in</code><span></span></a></li>
<li><a href="#basic-sender" id="toc-basic-sender"><span class="toc-section-number">5.3</span>
<em><code class="sourceCode default">basic-sender</code></em><span></span></a></li>
<li><a href="#dependent_sender" id="toc-dependent_sender"><span class="toc-section-number">5.4</span>
<code class="sourceCode default">dependent_sender</code><span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">6</span> Implementation
Experience<span></span></a></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">7</span> Proposed
Wording<span></span></a></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">8</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">9</span> References<span></span></a></li>
</ul>
</div>
<div style="text-align: right;">
<p><em>“Only the exceptional paths bring exceptional glories!”</em><br />
— Mehmet Murat Ildan</p>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>The hardest part of writing a sender algorithm is often the
computation of its completion signatures, an intricate meta-programming
task. Using sender algorithms incorrectly leads to large,
incomprehensible errors deep within the completion-signatures
meta-program. What is needed is a way to propagate type errors
automatically to the API boundary where they can be reported concisely,
much the way exceptions do for runtime errors.</p>
<p>Support for exceptions during constant-evaluation was recently
accepted into the Working Draft for C++26. We can take advantage of this
powerful new feature to easily propagate type errors during the
computation of a sender’s completion signatures. This significantly
improves the diagnostics users are likely to encounter while also
simplifying the job of writing new sender algorithms.</p>
<h1 data-number="2" id="executive-summary"><span class="header-section-number">2</span> Executive Summary<a href="#executive-summary" class="self-link"></a></h1>
<p>This paper proposes the following changes to the working draft with
the addition of <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span>. Subsequent
sections will address the motivation and the designs in detail.</p>
<ol type="1">
<li>Change <code class="sourceCode default">std::execution::get_completion_signatures</code>
from a customization point object that accepts a sender and (optionally)
an environment to a <code class="sourceCode default">consteval</code>
function template that takes no arguments, as follows:</li>
</ol>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> get_completion_signatures_t <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>Sndr<span class="op">&amp;&amp;</span>, Env<span class="op">&amp;&amp;...)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> get_completion_signatures <span class="op">{}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> <em><code class="sourceCode default">valid-completion-signatures</code></em> <span class="kw">auto</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<ol start="2" type="1">
<li>Change the mechanism by which senders customize
<code class="sourceCode default">get_completion_signatures</code> from a
member function that accepts the <em>cv</em>-qualified sender object and
an optional environment object to a
<code class="sourceCode default">static constexpr</code> function
template that take the sender and environment types as template
parameters.</li>
</ol>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_sender <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Self, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em><code class="sourceCode default">some-predicate</code></em><span class="op">&lt;</span>Self, Env<span class="op">...&gt;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> get_completion_signatures<span class="op">(</span><span class="kw">this</span> Self<span class="op">&amp;&amp;</span>, Env<span class="op">&amp;&amp;)</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> completion_signatures<span class="op">&lt;</span><span class="co">/* … */</span><span class="op">&gt;()</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_sender <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Self, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(!</span><em><code class="sourceCode default">some-predicate</code></em><span class="op">&lt;</span>Self, Env<span class="op">...&gt;)</span> <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <em><code class="sourceCode default">a-helpful-diagnostic</code></em><span class="op">()</span>; <span class="co">// &lt;--- LOOK!</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> completion_signatures<span class="op">&lt;</span><span class="co">/* … */</span><span class="op">&gt;()</span>;</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<ol start="3" type="1">
<li>Change the
<code class="sourceCode default">sender_in&lt;Sender, Env...&gt;</code>
concept to test that <code class="sourceCode default">get_completion_signatures&lt;Sndr, Env...&gt;()</code>
is a constant expression.</li>
</ol>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> sender_in <span class="op">=</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  sender<span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span>queryable<span class="op">&lt;</span>Env<span class="op">&gt;</span> <span class="op">&amp;&amp;...)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Env<span class="op">&amp;&amp;...</span> env<span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> get_completion_signatures<span class="op">(</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>Sndr<span class="op">&gt;(</span>sndr<span class="op">)</span>,</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>forward<span class="op">&lt;</span>Env<span class="op">&gt;(</span>env<span class="op">)...)</span> <span class="op">}</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>            <span class="op">-&gt;</span> <em><code class="sourceCode default">valid-completion-signatures</code></em>;</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">auto</span><span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em><code class="sourceCode default">is-constant</code></em> <span class="op">=</span> <span class="kw">true</span>; <span class="co">// exposition only</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> sender_in <span class="op">=</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  sender<span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span>queryable<span class="op">&lt;</span>Env<span class="op">&gt;</span> <span class="op">&amp;&amp;...)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">is-constant</code></em><span class="op">&lt;</span>get_completion_signatures<span class="op">&lt;</span>Sndr, Env<span class="op">...&gt;()&gt;</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<ol start="4" type="1">
<li><p>In the exposition-only
<em><code class="sourceCode default">basic-sender</code></em> class
template, specify under what conditions its
<code class="sourceCode default">get_completion_signatures</code> static
member function is ill-formed when called without an
<code class="sourceCode default">Env</code> template parameter (see
proposed wording for details).</p></li>
<li><p>Add a <code class="sourceCode default">dependent_sender</code>
concept that is modeled by sender types that do not know how they will
complete independent of their execution environment.</p></li>
<li><p>Remove the
<code class="sourceCode default">transform_completion_signatures</code>
alias template (to be later replaced with a
<code class="sourceCode default">consteval</code> function that does the
same job and that throws on error).</p></li>
</ol>
<h1 data-number="3" id="revision-history"><span class="header-section-number">3</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="3.1" id="r2"><span class="header-section-number">3.1</span> R2<a href="#r2" class="self-link"></a></h2>
<ul>
<li><p>Move the nice-to-haves into a separate paper (TBD).</p></li>
<li><p>Drop support for specifying a sender’s completion signatures with
a nested type alias.</p></li>
<li><p>Promote the exposition-only
<em><code class="sourceCode default">dependent-sender-error</code></em>
class to <code class="sourceCode default">std::execution::dependent_sender_error</code>.</p></li>
<li><p>Change <code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>::<em><code class="sourceCode default">check-types</code></em></code>
and all its customizations from
<code class="sourceCode default">constexpr</code> to
<code class="sourceCode default">consteval</code>.</p></li>
<li><p>Merge the proposed wording of <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span> into this paper’s proposed
wording for ease of wording review.</p></li>
</ul>
<h2 data-number="3.2" id="r1"><span class="header-section-number">3.2</span> R1<a href="#r1" class="self-link"></a></h2>
<p>Since R0, a significant fraction of C++26’s
<code class="sourceCode default">std::execution</code> has been
implemented with the design changes proposed by this paper. Several bugs
in R0 have been found and fixed as a result.</p>
<p>In addition, this paper exposed <a href="https://github.com/cplusplus/sender-receiver/issues/317">several
bugs</a> in the Working Draft for C++26. As those bugs relate to the
computation of completion signatures, R1 integrates the proposed fixes
for those bugs.</p>
<ul>
<li>Fix the specification of <code class="sourceCode default">std::execution::get_completion_signatures</code>
which was the victim of an incomplete last-minute edit.</li>
<li>Add support for awaitables, which was dropped accidentally, back to
<code class="sourceCode default">get_completion_signatures</code>.</li>
<li>Change proposed replacement for
<code class="sourceCode default">transform_completion_signatures</code>
to take a transform function for the stopped completion signature
instead of a
<code class="sourceCode default">completion_signatures</code>
object.</li>
<li>Add missing semantic constraints to <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;Tag&gt;::<em><code class="sourceCode default">check-types</code></em></code>
customizations.</li>
<li>Add missing syntactic constraint on <code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>&lt;Tag&gt;::get_completion_signatures</code>.</li>
<li>Strengthen the <em>Mandates</em> on
<code class="sourceCode default">std::execution::connect</code>.</li>
<li>Fixed the constraint on <code class="sourceCode default">stopped_as_optional.transform_sender(sndr, env)</code>.</li>
<li>Report type errors from the
<code class="sourceCode default">let_*</code>,
<code class="sourceCode default">schedule_from</code>,
<code class="sourceCode default">into_variant</code>,
<code class="sourceCode default">split</code>, and
<code class="sourceCode default">when_all</code> algorithms when the
prececessor’s result datums cannot be copied into intermediate
storage.</li>
<li>Add proposed wording for the nice-to-have features:
<ul>
<li><code class="sourceCode default">eptr_completion_if</code></li>
<li><code class="sourceCode default">make_completion_signatures</code></li>
<li><code class="sourceCode default">transform_completion_signatures</code>
(a <code class="sourceCode default">constexpr</code> function
version)</li>
<li><code class="sourceCode default">invalid_completion_signature</code></li>
</ul></li>
<li>Integrate proposed fix for <a href="https://github.com/cplusplus/sender-receiver/issues/311">cplusplus/sender-receiver#311</a>,
“<code class="sourceCode default">stopped_as_optional</code> tests
constraints satisfaction of self instead of child”.</li>
<li>Integrate proposed fix for <a href="https://github.com/cplusplus/sender-receiver/issues/317">cplusplus/sender-receiver#317</a>,
“Several algorithms are not applying
<em><code class="sourceCode default">FWD-ENV</code></em> as they
should”.</li>
<li>Integrate proposed fix for <a href="https://github.com/cplusplus/sender-receiver/issues/318">cplusplus/sender-receiver#318</a>,
“specification of <code class="sourceCode default">as-sndr2(Sig)</code>
in [exec.let] is incomplete”.</li>
<li>Integrate proposed fix for <a href="https://github.com/cplusplus/sender-receiver/issues/319">cplusplus/sender-receiver#319</a>,
“<code class="sourceCode default">let_[*].transform_env</code> is
specified in terms of the <code class="sourceCode default">let_*</code>
sender itself instead of its child”.</li>
<li>Fix paragraph numbering.</li>
</ul>
<h2 data-number="3.3" id="r0"><span class="header-section-number">3.3</span> R0<a href="#r0" class="self-link"></a></h2>
<ul>
<li>Initial revision</li>
</ul>
<h1 data-number="4" id="motivation"><span class="header-section-number">4</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>This paper exists principly to improve the experience of users who
make type errors in their sender expressions by leveraging exceptions
during constant- evaluation. It is a follow-on of <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span>, which defines a category of
“non-dependent” senders that can and must be type-checked early.</p>
<p>Senders have a construction phase and a subsequent connection phase.
Prior to P3164, all type-checking of senders happened at the connection
phase (when a sender is connected to a receiver). P3164 mandates that
the sender algorithms type-check non-dependent senders, moving the
diagnostic closer to the source of the error.</p>
<p>This paper addresses the <em>quality</em> of those diagnostics, as
well as the diagnostics users encounter when a dependent sender fails
type-checking at connection time.</p>
<p>Senders are expression trees, and type errors can happen deep within
their structure. If programmed naively, ill-formed senders would
generate megabytes of incomprehensible diagnostics. The challenge is to
report type errors <em>concisely</em> and <em>comprehensibly</em>, at
the right level of abstraction.</p>
<p>Doing this requires propagating domain-specific descriptions of type
errors out of the completion signatures meta-program so they can be
reported concisely. Such error detection and propagation is very
cumbersome in template meta-programming.</p>
<p>The C++ solution to error propagation is exceptions. With the
adoption of <span class="citation" data-cites="P3068R6">[<a href="#ref-P3068R6" role="doc-biblioref">P3068R6</a>]</span>, C++26 has
gained the ability to throw and catch exceptions during
constant-evaluation. If we express the computation of completion
signatures as a <code class="sourceCode default">constexpr</code>
meta-program, we can use exceptions to propagate type errors. This
greatly improves diagnostics and even simplifies the code that computes
completion signatures.</p>
<p>This paper proposes changes to
<code class="sourceCode default">std::execution</code> that make the
computation of a sender’s completion signatures an evaluation of a
<code class="sourceCode default">constexpr</code> function. It also
specifies the conditions under which the computation is to exit with an
exception.</p>
<h2 data-number="4.1" id="example"><span class="header-section-number">4.1</span> Example<a href="#example" class="self-link"></a></h2>
<p>How good are <code class="sourceCode default">std::execution</code>’s
diagnostics with <code class="sourceCode default">constexpr</code>
exceptions? Let’s consider a user that makes a simple mistake in their
sender expression:</p>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> stdex <span class="op">=</span> std<span class="op">::</span>execution;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> sndr <span class="op">=</span> stdex<span class="op">::</span>just<span class="op">(</span><span class="dv">42</span><span class="op">)</span> <span class="op">|</span> stdex<span class="op">::</span>then<span class="op">([]()</span> <span class="op">{</span> <span class="co">/*…*/</span> <span class="op">})</span>;</span></code></pre></div>
</blockquote>
<p>This is an error because the nullary lambda cannot be called with the
integer that <code class="sourceCode default">just(42)</code> completes
with.</p>
<p>With <code class="sourceCode default">constexpr</code> exceptions,
the resulting diagnostic is blissfully direct:</p>
<h3 data-number="4.1.1" id="with-constexpr-exceptions"><span class="header-section-number">4.1.1</span> With
<code class="sourceCode default">constexpr</code> exceptions:<a href="#with-constexpr-exceptions" class="self-link"></a></h3>
<blockquote>
<div class="sourceCode">
<pre class="sourceCode"><code class="sourceCode">
<span><b>&lt;source&gt;:658:3: <span style="color:red">error: </span>call to immediate function &#39;operator|&lt;_basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&#39;
is not a constant expression</b></span>
 2212 |   <span style="color:blue">auto</span> sndr = just(<span style="color:green">42</span>) | then([](){});
      |             <b><span style="color:green">  ^</span></b>
<span><b>&lt;source&gt;:658:3: <span style="color:cyan">note:</span></b> &#39;operator|&lt;_basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&#39; is an immediate function
because its body contains a call to an immediate function &#39;_make_sender&lt;then_t, (lambda at &lt;source&gt;:2212:
31), _basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&#39; and that call is not a constant expression
 1912 |       <span style="color:blue">return</span> transform_sender(dom, _make_sender(Algorithm, std::move(_self.data_), sndr));
      |                                  <b><span style="color:green"> <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b></span></b>
<span><b>&lt;source&gt;:658:3: <span style="color:cyan">note:</span></b> unhandled exception of type &#39;_sender_type_check_failure&lt;const char *, <span style="background-color:yellow">IN_ALGORITHM&lt;
then&gt;, WITH_FUNCTION ((lambda at &lt;source&gt;:2212:31)), WITH_ARGUMENTS (int)&gt;&#39; with content {{{}}, &amp;&quot;The fun
ction passed to std::execution::then is not callable with the values sent by the predecessor sender.&quot;[<span style="color:green">0</span>]}</span>
thrown from here
  876 |     <span style="color:blue">throw</span> _sender_type_check_failure&lt;Values...[<span style="color:green">0</span>], What...&gt;(values...);
      |           <b><span style="color:green">^</span></b></code></pre>
</div>
</blockquote>
<p>The above is the <em>complete</em> diagnostic, regardless of how
deeply nested the type error is.</p>
<p>In contrast, the following is the diagnostic we get without
<code class="sourceCode default">constexpr</code> exceptions. Notice
that the backtrace is truncated; the actual error is considerably
longer.</p>
<h3 data-number="4.1.2" id="without-constexpr-exceptions"><span class="header-section-number">4.1.2</span> Without
<code class="sourceCode default">constexpr</code> exceptions:<a href="#without-constexpr-exceptions" class="self-link"></a></h3>
<blockquote style="font-size:85%">
<div class="sourceCode">
<pre class="sourceCode"><code class="sourceCode">
<b>&lt;source&gt;:1912:36: <span style="color:red">error:</span> call to immediate function &#39;operator|&lt;_basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&#39; is not a constant 
expression</b>
 2212 |   <span style="color:blue">auto</span> sndr = just(<span style="color:green">42</span>) | then([](){});
      |              <b><span style="color:green"> ^</span></b>
<b>&lt;source&gt;:1912:36: <span style="color:cyan">note:</span></b> &#39;operator|&lt;_basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&#39; is an immediate function because its body cont
ains a call to an immediate function &#39;_make_sender&lt;then_t, (lambda at &lt;source&gt;:2212:31), _basic_sender&lt;just_t, _tupl&lt;nullptr, 
int&gt;&gt;&gt;&#39; and that call is not a constant expression
 1912 |       <span style="color:blue">return</span> transform_sender(dom, _make_sender(Algorithm, std::move(_self.data_), sndr));
      |                                   <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:876:5: <span style="color:cyan">note:</span></b> subexpression not valid in a constant expression
  876 |     <span style="color:blue">throw</span> _sender_type_check_failure&lt;Values...[<span style="color:green">0</span>], What...&gt;(values...);
      |    <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:1990:16: <span style="color:cyan">note:</span></b> in call to &#39;invalid_completion_signature&lt;IN_ALGORITHM&lt;then&gt;, WITH_FUNCTION ((lambda at &lt;source&gt;:2212:3
1)), WITH_ARGUMENTS (int), const char *&gt;(&amp;&quot;The function passed to std::execution::then is not callable with the values sent by
 the predecessor sender.&quot;[<span style="color:green">0</span>])&#39;
 1990 |         <span style="color:blue">return</span> invalid_completion_signature&lt;IN_ALGORITHM&lt;then&gt;,
      |               <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
 1991 |                                             <span style="color:blue">struct</span> WITH_FUNCTION(Fn),
      |                                            <b><span style="color:green"> ~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
 1992 |                                             <span style="color:blue">struct</span> WITH_ARGUMENTS(As...)&gt;(
      |                                            <b><span style="color:green"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
 1993 |         &quot;The function passed to std::execution::then is not callable with the&quot;
      |        <b><span style="color:green"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
 1994 |         &quot; values sent by the predecessor sender.&quot;);
      |        <b><span style="color:green"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:885:10: <span style="color:cyan">note:</span></b> in call to &#39;fn.operator()&lt;int&gt;()&#39;
  885 |   <span style="color:blue">return</span> fn.template operator()&lt;As...&gt;();
      |         <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:897:12: <span style="color:cyan">note:</span></b> in call to &#39;_transform_expr&lt;int, _impls_for&lt;then_t&gt;::(lambda at &lt;source&gt;:1988:5)&gt;(fn..)&#39;
  897 |     <span style="color:blue">return</span> ::_transform_expr&lt;As...&gt;(fn);
      |           <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:923:14: <span style="color:cyan">note:</span></b> in call to &#39;_apply_transform&lt;int, _impls_for&lt;then_t&gt;::(lambda at &lt;source&gt;:1988:5)&gt;(fn..)&#39;
  923 |       <span style="color:blue">return</span> _apply_transform&lt;Ts...&gt;(value_fn);
      |             <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:930:13: <span style="color:cyan">note:</span></b> in call to &#39;transform1.operator()&lt;set_value_t, int&gt;(nullptr)&#39;
  930 |     <span style="color:blue">return</span> (transform1(sigs) +...+ completion_signatures());
      |            <b><span style="color:green"> ^~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:804:12: <span style="color:cyan">note:</span></b> (skipping 6 calls in backtrace; use -fconstexpr-backtrace-limit=<span style="color:green">0</span> to see all)
  804 |     <span style="color:blue">return</span> fn(_normalized_sig_t&lt;Sigs&gt;()...);
      |           <b><span style="color:green"> ^</span></b>
<b>&lt;source&gt;:1206:31: <span style="color:cyan">note:</span></b> in call to &#39;get_completion_signatures&lt;_basic_sender&lt;then_t, (lambda at &lt;source&gt;:2212:31), _basic_sende
r&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&gt;()&#39;
 1206 |     <span style="color:blue">return</span> _CHECKED_COMPLSIGS(_GET_COMPLSIGS(Sndr, Env...));
      |           <b><span style="color:green"> ~~~~~~~~~~~~~~~~~~~</span></b>^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<b>&lt;source&gt;:1188:3: <span style="color:cyan">note:</span></b> expanded from macro &#39;_GET_COMPLSIGS&#39;
 1188 |   std::remove_reference_t&lt;Sndr&gt;::template get_completion_signatures&lt;Sndr __VA_OPT__(,) __VA_ARGS__&gt;()
      |  <b><span style="color:green"> ^</span></b>
<b>&lt;source&gt;:1190:34: <span style="color:cyan">note:</span></b> expanded from macro &#39;_CHECKED_COMPLSIGS&#39;
 1190 | #define _CHECKED_COMPLSIGS(...) (__VA_ARGS__, ::_checked_complsigs&lt;decltype(__VA_ARGS__)&gt;())
      |                                 <b><span style="color:green"> ^~~~~~~~~~~</span></b>
<b>&lt;source&gt;:1230:10: <span style="color:cyan">note:</span></b> in call to &#39;_get_completion_signatures_helper&lt;_basic_sender&lt;then_t, (lambda at &lt;source&gt;:2212:31), _bas
ic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&gt;()&#39;
 1230 |   <span style="color:blue">return</span> _get_completion_signatures_helper&lt;Sndr&gt;();
      |         <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:1872:12: <span style="color:cyan">note:</span></b> in call to &#39;get_completion_signatures&lt;_basic_sender&lt;then_t, (lambda at &lt;source&gt;:2212:31), _basic_sende
r&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;&gt;()&#39;
 1872 |     (void) get_completion_signatures&lt;Sender&gt;();
      |           <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:1912:36: <span style="color:cyan">note:</span></b> in call to &#39;_make_sender&lt;then_t, (lambda at &lt;source&gt;:2212:31), _basic_sender&lt;just_t, _tupl&lt;nullptr, in
t&gt;&gt;&gt;({{}}, {}, {{}, {}, {{<span style="color:green">42</span>}}})&#39;
 1912 |       <span style="color:blue">return</span> transform_sender(dom, _make_sender(Algorithm, std::move(_self.data_), sndr));
      |                                   <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></b>
<b>&lt;source&gt;:2212:15: <span style="color:cyan">note:</span></b> in call to &#39;operator|&lt;_basic_sender&lt;just_t, _tupl&lt;nullptr, int&gt;&gt;&gt;({{}, {}, {{<span style="color:green">42</span>}}}, {{}})&#39;
 2212 |   <span style="color:blue">auto</span> sndr = just(<span style="color:green">42</span>) | then([](){});
      |              <b><span style="color:green"> ^~~~~~~~~~~~~~~~~~~~~~~</span></b></code></pre>
</div>
</blockquote>
<p>The code that generated these diagnostics can be found <a href="https://gist.github.com/ericniebler/0896776ab1c8f5b7f77d7094c0400df5">here</a>
or at <a href="https://godbolt.org/z/rPEqWz693">https://godbolt.org/z/rPEqWz693</a></p>
<h1 data-number="5" id="proposed-design"><span class="header-section-number">5</span> Proposed Design<a href="#proposed-design" class="self-link"></a></h1>
<h2 data-number="5.1" id="get_completion_signatures"><span class="header-section-number">5.1</span>
<code class="sourceCode default">get_completion_signatures</code><a href="#get_completion_signatures" class="self-link"></a></h2>
<p>In the Working Draft, a sender’s completion signatures are determined
by the type of the expression <code class="sourceCode default">std::execution::get_completion_signatures(sndr, env)</code>
(or, after P3164, <code class="sourceCode default">std::execution::get_completion_signatures(sndr)</code>
for non-dependent senders). Only the type of the expression matters; the
expression itself is never evaluated.</p>
<p>In the design proposed by this paper, the
<code class="sourceCode default">get_completion_signatures</code>
expression must be constant-evaluated in order use exceptions to report
errors. To make it ammenable to constant evaluation, it must not accept
arguments with runtime values, so the expression is changed to <code class="sourceCode default">std::execution::get_completion_signatures&lt;Sndr, Env...&gt;()</code>,
where <code class="sourceCode default">get_completion_signatures</code>
is a <code class="sourceCode default">consteval</code> function.</p>
<p>If an unhandled exception propagates out of
<code class="sourceCode default">get_completion_signatures</code> the
program is ill-formed (because
<code class="sourceCode default">get_completion_signatures</code> is
<code class="sourceCode default">consteval</code>). The diagnostic
displays the type and value of the exception.</p>
<p><code class="sourceCode default">std::execution::get_completion_signatures&lt;Sndr, Env...&gt;()</code>
in turn calls <code class="sourceCode default">remove_reference_t&lt;Sndr&gt;::template get_completion_signatures&lt;Sndr, Env...&gt;()</code>,
which computes the completion signatures or throws as appropriate, as
shown below:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> exec <span class="op">=</span> std<span class="op">::</span>execution;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> void_sender <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> sender_concept <span class="op">=</span> exec<span class="op">::</span>sender_t;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Self, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> exec<span class="op">::</span>completion_signatures<span class="op">&lt;</span>exec<span class="op">::</span>set_value_t<span class="op">()&gt;()</span>;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* … more … */</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>To better support the
<code class="sourceCode default">constexpr</code> value-oriented
programming style, calls to <code class="sourceCode default">std::execution::get_completion_signatures</code>
from a <code class="sourceCode default">constexpr</code> function are
never ill-formed, and their return type is always a specialization of
the <code class="sourceCode default">completion_signatures</code>
template. <code class="sourceCode default">std::execution::get_completion_signatures</code>
reports errors by failing to be a constant expression.</p>
<h3 data-number="5.1.1" id="non-non-dependent-senders"><span class="header-section-number">5.1.1</span> <em>Non</em>-non-dependent
senders<a href="#non-non-dependent-senders" class="self-link"></a></h3>
<p><span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span> introduces the concept of
non-dependent senders: senders that have the same completion signatures
regardless of the receiver’s execution environment. For a sender type
<code class="sourceCode default">DependentSndr</code> whose completions
<em>do</em> depend on the environment, what should happen when the
sender’s completions are queried without an environment? That is, what
should the semantics be for <code class="sourceCode default">get_completion_signatures&lt;DependentSndr&gt;()</code>?</p>
<p><code class="sourceCode default">get_completion_signatures&lt;DependentSndr&gt;()</code>
should follow the general rule: it should be well-formed in a
<code class="sourceCode default">constexpr</code> function, and it
should have a
<code class="sourceCode default">completion_signatures</code> type. That
way, sender adaptors do not need to do anything special when computing
the completions of child senders that are dependent. So <code class="sourceCode default">get_completion_signatures&lt;DependentSndr&gt;()</code>
should throw.</p>
<p>If <code class="sourceCode default">get_completion_signatures&lt;Sndr&gt;()</code>
throws for dependent senders, and it also throws for non-dependent
senders that fail to type-check, how then do we distinguish between
valid dependent and invalid non-dependent senders? We can distinguish by
checking the type of the exception.</p>
<p>An example will help. Consider the
<code class="sourceCode default">read_env(q)</code> sender, a dependent
sender that sends the result of calling
<code class="sourceCode default">q</code> with the receiver’s
environment. It cannot compute its completion signatures without an
environment. The natural way for the
<code class="sourceCode default">read_env</code> sender to express that
is to require an <code class="sourceCode default">Env</code> parameter
to its customization of
<code class="sourceCode default">get_completion_signatures</code>:</p>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> exec <span class="op">=</span> std<span class="op">::</span>execution;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Query<span class="op">&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> read_env_sender <span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> sender_concept <span class="op">=</span> exec<span class="op">::</span>sender_t;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Self, <span class="kw">class</span> Env<span class="op">&gt;</span> <span class="co">// </span><span class="al">NOTE</span><span class="co">: Env is not optional!</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(!</span>std<span class="op">::</span>invocable<span class="op">&lt;</span>Query, Env<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">throw</span> <em><code class="sourceCode default">exception-type-goes-here</code></em><span class="op">()</span>;</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>      <span class="kw">using</span> Result <span class="op">=</span> std<span class="op">::</span>invoke_result_t<span class="op">&lt;</span>Query, Env<span class="op">&gt;</span>;</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> exec<span class="op">::</span>completion_signatures<span class="op">&lt;</span>exec<span class="op">::</span>set_value_t<span class="op">(</span>Result<span class="op">)&gt;()</span>;</span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* … more … */</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>That makes <code class="sourceCode default">read_env_sender&lt;Q&gt;::get_completion_signatures&lt;Sndr&gt;()</code>
an ill-formed expression, which the
<code class="sourceCode default">get_completion_signatures</code>
function can detect. In such cases, it would throw an exception of a
special type that it can catch later when distinguishing between
dependent and non-dependent senders.</p>
<h3 data-number="5.1.2" id="implementation"><span class="header-section-number">5.1.2</span> Implementation<a href="#implementation" class="self-link"></a></h3>
<p>Since the design has several parts, reading the implementation of
<code class="sourceCode default">get_completion_signatures</code> is
probably the easiest way to understand it. The implementation is shown
below with comments describing the parts.</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This macro expands to an invocation of SNDR&#39;s get_completion_signatures</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co">// customization.</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#define GET_COMPLSIGS</span><span class="op">(</span>SNDR,<span class="pp"> </span><span class="op">...)</span><span class="pp"> </span>std<span class="op">::</span>remove_reference_t<span class="op">&lt;</span>SNDR<span class="op">&gt;::</span><span class="kw">template</span><span class="pp">      </span>\</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="pp">    </span>get_completion_signatures<span class="op">&lt;</span>SNDR<span class="pp"> </span><span class="ot">__VA_OPT__</span><span class="op">(</span>,<span class="op">)</span><span class="pp"> </span><span class="ot">__VA_ARGS__</span><span class="op">&gt;()</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="co">// This macro expands to an evaluation of EXPR, followed by an invocation</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="co">// of the _checked_complsigs function which validates its type.</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="pp">#define CHECK_COMPLSIGS</span><span class="op">(</span>EXPR<span class="op">)</span><span class="pp"> </span><span class="op">(</span>EXPR,<span class="pp"> </span>_check_complsigs<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>EXPR<span class="op">)&gt;())</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="co">// This helper ensures that the passed type is indeed a specialization of the</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="co">// completion_signatures class template, and throws if it is not.</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Completions<span class="op">&gt;</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> _check_complsigs<span class="op">()</span> <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em><code class="sourceCode default">valid-completion-signatures</code></em><span class="op">&lt;</span>Completions<span class="op">&gt;)</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// We got a type that is a specialization of the completion_signatures</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// class template representing the sender&#39;s completions. Return it.</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> Completions<span class="op">()</span>;</span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// throw unconditionally but make sure the return type is deduced to</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// be `completion_signatures&lt;&gt;`. That way, a sender adaptor can ask</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>    <span class="co">// a child for its completions and take for granted that the return</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// type is a specialization of `completion_signatures&lt;&gt;`</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(</span><span class="cf">throw</span> <em><code class="sourceCode default">unspecified</code></em>, completion_signatures<span class="op">())</span>;</span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> _get_completion_signatures_helper<span class="op">()</span> <span class="op">{</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The following `if` tests whether GET_COMPLSIGS(Sndr, Env...)</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// is a well-formed expression.</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> GET_COMPLSIGS<span class="op">(</span>Sndr, Env<span class="op">...)</span>; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>    <span class="co">// The GET_COMPLSIGS(Sndr, Env...) expression is well-formed, but it may</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// throw an exception or otherwise fail to be a constant expression.</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// By evaluating it, we cause its exception and its non-constexpr-ness to</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// propagate. Then CHECK_COMPLSIGS ensures that its type is indeed</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>    <span class="co">// a specialization of the completion_signatures class template.</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> CHECK_COMPLSIGS<span class="op">(</span>GET_COMPLSIGS<span class="op">(</span>Sndr, Env<span class="op">...))</span>;</span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// The following `if` does the same as above, but for GET_COMPLSIGS(Sndr).</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true" tabindex="-1"></a>  <span class="co">// A non-dependent sender may announce itself by way of this signature.</span></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">requires</span> <span class="op">{</span> GET_COMPLSIGS<span class="op">(</span>Sndr<span class="op">)</span>; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Same as above: propagate any exceptions and non-constexpr-ness, and</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true" tabindex="-1"></a>    <span class="co">// verify the expression has the right type.</span></span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> CHECK_COMPLSIGS<span class="op">(</span>GET_COMPLSIGS<span class="op">(</span>Sndr<span class="op">))</span>;</span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true" tabindex="-1"></a>  <span class="co">// We can&#39;t recognize Sndr as a sender proper, but maybe it is awaitable,</span></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true" tabindex="-1"></a>  <span class="co">// in which case we can adapt it to be a sender.</span></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em><code class="sourceCode default">is-awaitable</code></em><span class="op">&lt;</span>Sndr, <em><code class="sourceCode default">env-promise</code></em><span class="op">&lt;</span>Env<span class="op">&gt;...&gt;)</span> <span class="op">{</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> completion_signatures<span class="op">&lt;</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true" tabindex="-1"></a>      <em><code class="sourceCode default">SET-VALUE-SIG</code></em><span class="op">(</span><em><code class="sourceCode default">await-result-type</code></em><span class="op">&lt;</span>Sndr, <em><code class="sourceCode default">env-promise</code></em><span class="op">&lt;</span>Env<span class="op">&gt;...&gt;)</span>,  <span class="co">//  ([exec.snd.concepts])</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true" tabindex="-1"></a>      set_error_t<span class="op">(</span>exception_ptr<span class="op">)</span>,</span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true" tabindex="-1"></a>      set_stopped_t<span class="op">()&gt;()</span>;</span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true" tabindex="-1"></a>  <span class="co">// If none of the above expressions are well-formed, then we don&#39;t know</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true" tabindex="-1"></a>  <span class="co">// the sender&#39;s completions. If we are testing without an environment, then</span></span>
<span id="cb10-55"><a href="#cb10-55" aria-hidden="true" tabindex="-1"></a>  <span class="co">// we assume Sndr is a dependent sender. Throw an exception that</span></span>
<span id="cb10-56"><a href="#cb10-56" aria-hidden="true" tabindex="-1"></a>  <span class="co">// communicates that.</span></span>
<span id="cb10-57"><a href="#cb10-57" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Env<span class="op">)</span> <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-58"><a href="#cb10-58" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(</span><span class="cf">throw</span> dependent_sender_error<span class="op">()</span>, completion_signatures<span class="op">())</span>;</span>
<span id="cb10-59"><a href="#cb10-59" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-60"><a href="#cb10-60" aria-hidden="true" tabindex="-1"></a>  <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-61"><a href="#cb10-61" aria-hidden="true" tabindex="-1"></a>    <span class="co">// We cannot compute the completion signatures for this sender and</span></span>
<span id="cb10-62"><a href="#cb10-62" aria-hidden="true" tabindex="-1"></a>    <span class="co">// environment. Give up and throw an exception.</span></span>
<span id="cb10-63"><a href="#cb10-63" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(</span><span class="cf">throw</span> <em><code class="sourceCode default">unspecified</code></em>, completion_signatures<span class="op">())</span>;</span>
<span id="cb10-64"><a href="#cb10-64" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-65"><a href="#cb10-65" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-66"><a href="#cb10-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-67"><a href="#cb10-67" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb10-68"><a href="#cb10-68" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span> <span class="op">-&gt;</span> _valid_completion_signatures <span class="kw">auto</span> <span class="op">{</span></span>
<span id="cb10-69"><a href="#cb10-69" aria-hidden="true" tabindex="-1"></a>  <span class="co">// There is no environment, which means we are asking for the sender&#39;s non-</span></span>
<span id="cb10-70"><a href="#cb10-70" aria-hidden="true" tabindex="-1"></a>  <span class="co">// dependent completion signatures. If the sender is dependent, this will</span></span>
<span id="cb10-71"><a href="#cb10-71" aria-hidden="true" tabindex="-1"></a>  <span class="co">// exit with a special exception type.</span></span>
<span id="cb10-72"><a href="#cb10-72" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> _get_completion_signatures_helper<span class="op">&lt;</span>Sndr<span class="op">&gt;()</span>;</span>
<span id="cb10-73"><a href="#cb10-73" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-74"><a href="#cb10-74" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-75"><a href="#cb10-75" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Env<span class="op">&gt;</span></span>
<span id="cb10-76"><a href="#cb10-76" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="kw">auto</span> get_completion_signatures<span class="op">()</span> <span class="op">-&gt;</span> _valid_completion_signatures <span class="kw">auto</span> <span class="op">{</span></span>
<span id="cb10-77"><a href="#cb10-77" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Apply a lazy sender transform if one exists before computing the completion signatures:</span></span>
<span id="cb10-78"><a href="#cb10-78" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> Domain <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>_get_domain_late<span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>Sndr<span class="op">&gt;()</span>, std<span class="op">::</span>declval<span class="op">&lt;</span>Env<span class="op">&gt;()))</span>;</span>
<span id="cb10-79"><a href="#cb10-79" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> NewSndr <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>transform_sender<span class="op">(</span>Domain<span class="op">()</span>, std<span class="op">::</span>declval<span class="op">&lt;</span>Sndr<span class="op">&gt;()</span>, std<span class="op">::</span>declval<span class="op">&lt;</span>Env<span class="op">&gt;()))</span>;</span>
<span id="cb10-80"><a href="#cb10-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-81"><a href="#cb10-81" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> _get_completion_signatures_helper<span class="op">&lt;</span>NewSndr, Env<span class="op">&gt;()</span>;</span>
<span id="cb10-82"><a href="#cb10-82" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Given this definition of
<code class="sourceCode default">get_completion_signatures</code>, we
can implement a <code class="sourceCode default">dependent_sender</code>
concept as follows:</p>
<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Returns true when get_completion_signatures&lt;Sndr&gt;() throws a</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="co">// dependent_sender_error or a type dereived from it. Returns false when</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="co">// get_completion_signatures&lt;Sndr&gt;() returns normally (Sndr is non-dependent).</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">bool</span> <em><code class="sourceCode default">is-dependent-sender-helper</code></em><span class="op">()</span> <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span><span class="dt">void</span><span class="op">)</span> get_completion_signatures<span class="op">&lt;</span>Sndr<span class="op">&gt;()</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">catch</span> <span class="op">(</span>dependent_sender_error<span class="op">&amp;)</span> <span class="op">{</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="co">// If get_completion_signatures&lt;Sndr&gt;() throws an exception other than</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="co">// dependent_sender_error, then <em><code class="sourceCode default">is-dependent-sender-helper</code></em>&lt;Sndr&gt;() will</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="co">// fail to be a constant expression and so 2ill not be a valid non-type</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a><span class="co">// template parameter to bool_constant. Therefore, dependent_sender&lt;Sndr&gt; will</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a><span class="co">// be false.</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> dependent_sender <span class="op">=</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>  sender<span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>  bool_constant<span class="op">&lt;</span><em><code class="sourceCode default">is-dependent-sender-helper</code></em><span class="op">&lt;</span>Sndr<span class="op">&gt;()&gt;::</span>value;</span></code></pre></div>
</blockquote>
<p>After the adoption of <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span>, the sender
algorithms are all required to return senders that are either dependent
or else that type-check successfully. This paper proposes adding that
type-checking as a <em>Mandates</em> on the exposition-only
<em><code class="sourceCode default">make-sender</code></em> function
template that all the algorithms use to construct their return
value.</p>
<p>Users who define their own sender algorithms can use
<code class="sourceCode default">dependent_sender</code> and
<code class="sourceCode default">get_completion_signatures</code> to
perform early type-checking of their own sender types using a helper
such as the following:</p>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> _type_check_sender<span class="op">(</span>Sndr sndr<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(!</span>dependent_sender<span class="op">&lt;</span>Sndr<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// This line will fail to compile if Sndr fails its type checking. We</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// don&#39;t want to perform this type checking when Sndr is dependent, though.</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Without an environment, the sender doesn&#39;t know its completions.</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span><span class="dt">void</span><span class="op">)</span> get_completion_signatures<span class="op">&lt;</span>Sndr<span class="op">&gt;()</span>;</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> sndr;</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Using this helper, a <code class="sourceCode default">then</code>
algorithm might type-check its returned senders as follows:</p>
<blockquote>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">struct</span> then_t <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>sender Sndr, <span class="kw">class</span> Fn<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>Sndr sndr, Fn fn<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> _type_check_sender<span class="op">(</span>_then_sender<span class="op">{</span>std<span class="op">::</span>move<span class="op">(</span>sndr<span class="op">)</span>, std<span class="op">::</span>move<span class="op">(</span>fn<span class="op">)})</span>;</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> then <span class="op">{}</span>;</span></code></pre></div>
</blockquote>
<h2 data-number="5.2" id="sender_in"><span class="header-section-number">5.2</span>
<code class="sourceCode default">sender_in</code><a href="#sender_in" class="self-link"></a></h2>
<p>With the above changes, we need to tweak the
<code class="sourceCode default">sender_in</code> concept to require
that <code class="sourceCode default">get_completion_signatures&lt;Sndr, Env...&gt;()</code>
is a constant expression.</p>
<p>The changes to <code class="sourceCode default">sender_in</code>
relative to <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span> are as
follows:</p>
<blockquote>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template &lt;auto&gt;</code></span></ins></span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept <em>is-constant</em> = true; // exposition only</code></span></ins></span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span><span class="op">...</span> Env<span class="op">&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> sender_in <span class="op">=</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    sender<span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Env<span class="op">)</span> <span class="op">&lt;=</span> <span class="dv">1</span><span class="op">)</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span>queryable<span class="op">&lt;</span>Env<span class="op">&gt;</span> <span class="op">&amp;&amp;...)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em>is-constant</em>&lt;get_completion_signatures&lt;Sndr, Env...&gt;()&gt;;</code></span></ins></span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">requires (Sndr&amp;&amp; sndr, Env&amp;&amp;... env) {</code></span></del></span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">{ get_completion_signatures(std::forward&lt;Sndr&gt;(sndr), std::forward&lt;Env&gt;(env)...) }</code></span></del></span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">-&gt; <em>valid-completion-signatures</em>;</code></span></del></span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">};</code></span></del></span></span></code></pre></div>
</blockquote>
<h2 data-number="5.3" id="basic-sender"><span class="header-section-number">5.3</span>
<em><code class="sourceCode default">basic-sender</code></em><a href="#basic-sender" class="self-link"></a></h2>
<p>The sender algorithms are expressed in terms of the exposition-only
class template
<em><code class="sourceCode default">basic-sender</code></em>. The
mechanics of computing completion signatures is not specified, however,
so very little change there is needed to implement this proposal.</p>
<p>We do, however, have to say when <code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>::get_completion_signatures&lt;Sndr&gt;()</code>
is ill-formed. In <span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span>,
non-dependent senders are dealt with by discussing whether or not a
sender’s potentially-evaluated completion operations are dependent on
the type of the receiver’s environment. In this paper, we make a similar
appeal when specifying whether or not <code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>::get_completion_signatures&lt;Sndr&gt;()</code>
is well-formed.</p>
<h2 data-number="5.4" id="dependent_sender"><span class="header-section-number">5.4</span>
<code class="sourceCode default">dependent_sender</code><a href="#dependent_sender" class="self-link"></a></h2>
<p>Users who write their own sender adaptors will also want to perform
early type-checking of senders that are not dependent. Therefore, they
need a way to determine whether or not a sender is dependent.</p>
<p>In the section <a href="#get_completion_signatures"><code class="sourceCode default">get_completion_signatures</code></a>
we show how the concept
<code class="sourceCode default">dependent_sender</code> can be
implemented in terms of this paper’s
<code class="sourceCode default">get_completion_signatures</code>
function template. By making this a public-facing concept, we give
sender adaptor authors a way to do early type-checking, just like the
standard adaptors.</p>
<h1 data-number="6" id="implementation-experience"><span class="header-section-number">6</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>A significant fraction of
<code class="sourceCode default">std::execution</code> has been
implemented with this design change. It can be found on <a href="https://godbolt.org/z/rPEqWz693">Compiler Explorer</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> and in <a href="https://gist.github.com/ericniebler/0896776ab1c8f5b7f77d7094c0400df5">this
GitHub gist</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>. This implementation includes all
the design elements that would stress the completion signature
computation including:</p>
<ul>
<li><p>Both dependent and non-dependent senders and sender adaptors,
with tests for both early and late diagnosis of type errors.</p></li>
<li><p>The exposition-only
<em><code class="sourceCode default">basic-sender</code></em> has been
implemented with the changes
<code class="sourceCode default">get_completion_signatures</code>
customization syntax and the new <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;Tag&gt;::<em><code class="sourceCode default">check-types</code></em></code>
customization, which has been used to implement and type-check all the
sender types, as specified.</p></li>
<li><p>A sender that is implemented via a lowering to another sender
type via a lazy <code class="sourceCode default">transform_sender</code>
customization
(<code class="sourceCode default">stopped_as_optional</code>).</p></li>
<li><p>Using awaitables as senders and <em>vice versa</em>.</p></li>
</ul>
<h1 data-number="7" id="proposed-wording"><span class="header-section-number">7</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: This
wording is relative to the current working draft with the addition of
<span class="citation" data-cites="P3164R4">[<a href="#ref-P3164R4" role="doc-biblioref">P3164R4</a>]</span> ]</span></p>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[async.ops]/13 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span> A
<dfn>completion signature</dfn> is a function type that describes a
completion operation. An asychronous operation has a finite set of
possible completion signatures corresponding to the completion
operations that the asynchronous operation potentially evaluates
([basic.def.odr]). For a completion function
<code class="sourceCode default">set</code>, receiver
<code class="sourceCode default">rcvr</code>, and pack of arguments
<code class="sourceCode default">args</code>, let
<code class="sourceCode default">c</code> be the completion operation
<code class="sourceCode default">set(rcvr, args...)</code>, and let
<code class="sourceCode default">F</code> be the function type <code class="sourceCode default">decltype(auto(set))(decltype((args))...)</code>.
A completion signature <code class="sourceCode default">Sig</code> is
associated with <code class="sourceCode default">c</code> if and only if
<code class="sourceCode default"><em><code class="sourceCode default">MATCHING-SIG</code></em>(Sig, F)</code>
is <code class="sourceCode default">true</code> ([exec.general]).
Together, a sender type and an environment type
<code class="sourceCode default">Env</code> determine the set of
completion signatures of an asynchronous operation that results from
connecting the sender with a receiver that has an environment of type
<code class="sourceCode default">Env</code>. The type of the receiver
does not affect an asychronous operation’s completion signatures, only
the type of the receiver’s environment. <span class="add" style="color: #006e28"><ins>A <dfn>non-dependent sender</dfn> is a
sender type whose completion signatures are knowable independent of an
execution environment.</ins></span></p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[execution.syn] as follows: ]</span></p>
<blockquote>
<p><b>Header <code class="sourceCode default">&lt;execution&gt;</code>
synopsis [execution.syn]</b></p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">= env&lt;&gt;</code></span></del></span><span class="op">&gt;</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> sender_in <span class="op">=</span> <em>see below</em>;</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr&gt;</code></span></ins></span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept dependent_sender = <em>see below</em>;</code></span></ins></span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> sender_to <span class="op">=</span> <em>see below</em>;</span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> <em><code class="sourceCode default">type-list</code></em>;                                           <span class="co">// exposition only</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">// [exec.getcomplsigs], completion signatures</code></span></del></span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">struct get_completion_signatures_t;</code></span></del></span></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">inline constexpr get_completion_signatures_t get_completion_signatures {};</code></span></del></span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>  <span class="ednote" style="color: #0000ff">[ Editor&#39;s note: <code class="sourceCode default">This alias is moved below and modified.</code>
]</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></del></span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">requires sender_in&lt;Sndr, Env...&gt;</code></span></del></span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">using completion_signatures_of_t = <em><code class="sourceCode default">call-result-t</code></em>&lt;get_completion_signatures_t, Sndr, Env...&gt;;</code></span></del></span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em><code class="sourceCode default">decayed-tuple</code></em> <span class="op">=</span> tuple<span class="op">&lt;</span>decay_t<span class="op">&lt;</span>Ts<span class="op">&gt;...&gt;</span>;                <span class="co">// exposition only</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env<span class="op">&gt;</span></span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em><code class="sourceCode default">single-sender-value-type</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;               <span class="co">// exposition only</span></span>
<span id="cb15-32"><a href="#cb15-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-33"><a href="#cb15-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env<span class="op">&gt;</span></span>
<span id="cb15-34"><a href="#cb15-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">single-sender</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;                        <span class="co">// exposition only</span></span>
<span id="cb15-35"><a href="#cb15-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-36"><a href="#cb15-36" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb15-37"><a href="#cb15-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-38"><a href="#cb15-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [exec.util], sender and receiver utilities</span></span>
<span id="cb15-39"><a href="#cb15-39" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [exec.util.cmplsig] <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">completion signatures</code></span></ins></span></span></span>
<span id="cb15-40"><a href="#cb15-40" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Fn<span class="op">&gt;</span></span>
<span id="cb15-41"><a href="#cb15-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">completion-signature</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;                   <span class="co">// exposition only</span></span>
<span id="cb15-42"><a href="#cb15-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-43"><a href="#cb15-43" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em><code class="sourceCode default">completion-signature</code></em><span class="op">...</span> Fns<span class="op">&gt;</span></span>
<span id="cb15-44"><a href="#cb15-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> completion_signatures <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">{}</code></span></del></span>;</span>
<span id="cb15-45"><a href="#cb15-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-46"><a href="#cb15-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sigs<span class="op">&gt;</span></span>
<span id="cb15-47"><a href="#cb15-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">valid-completion-signatures</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;            <span class="co">// exposition only</span></span>
<span id="cb15-48"><a href="#cb15-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-49"><a href="#cb15-49" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">struct dependent_sender_error : exception {};</code></span></ins></span></span>
<span id="cb15-50"><a href="#cb15-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-51"><a href="#cb15-51" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">// [exec.getcomplsigs]</code></span></ins></span></span>
<span id="cb15-52"><a href="#cb15-52" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb15-53"><a href="#cb15-53" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">consteval auto get_completion_signatures() -&gt; <em><code class="sourceCode default">valid-completion-signatures</code></em> auto;</code></span></ins></span></span>
<span id="cb15-54"><a href="#cb15-54" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-55"><a href="#cb15-55" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb15-56"><a href="#cb15-56" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">requires sender_in&lt;Sndr, Env...&gt;</code></span></ins></span></span>
<span id="cb15-57"><a href="#cb15-57" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">using completion_signatures_of_t = decltype(get_completion_signatures&lt;Sndr, Env...&gt;());</code></span></ins></span></span>
<span id="cb15-58"><a href="#cb15-58" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-59"><a href="#cb15-59" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">// [exec.util.cmplsig.trans]</code></span></del></span></span>
<span id="cb15-60"><a href="#cb15-60" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;</code></span></del></span></span>
<span id="cb15-61"><a href="#cb15-61" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> InputSignatures,</code></span></del></span></span>
<span id="cb15-62"><a href="#cb15-62" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> AdditionalSignatures = completion_signatures&lt;&gt;,</code></span></del></span></span>
<span id="cb15-63"><a href="#cb15-63" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class...&gt; class SetValue = <em><code class="sourceCode default">see below</code></em>,</code></span></del></span></span>
<span id="cb15-64"><a href="#cb15-64" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class&gt; class SetError = <em><code class="sourceCode default">see below</code></em>,</code></span></del></span></span>
<span id="cb15-65"><a href="#cb15-65" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> SetStopped = completion_signatures&lt;set_stopped_t()&gt;&gt;</code></span></del></span></span>
<span id="cb15-66"><a href="#cb15-66" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">using transform_completion_signatures = completion_signatures&lt;<em><code class="sourceCode default">see below</code></em>&gt;;</code></span></del></span></span>
<span id="cb15-67"><a href="#cb15-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-68"><a href="#cb15-68" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;</code></span></del></span></span>
<span id="cb15-69"><a href="#cb15-69" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">sender Sndr,</code></span></del></span></span>
<span id="cb15-70"><a href="#cb15-70" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">class Env = env&lt;&gt;,</code></span></del></span></span>
<span id="cb15-71"><a href="#cb15-71" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> AdditionalSignatures = completion_signatures&lt;&gt;,</code></span></del></span></span>
<span id="cb15-72"><a href="#cb15-72" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class...&gt; class SetValue = <em><code class="sourceCode default">see below</code></em>,</code></span></del></span></span>
<span id="cb15-73"><a href="#cb15-73" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class&gt; class SetError = <em><code class="sourceCode default">see below</code></em>,</code></span></del></span></span>
<span id="cb15-74"><a href="#cb15-74" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> SetStopped = completion_signatures&lt;set_stopped_t()&gt;&gt;</code></span></del></span></span>
<span id="cb15-75"><a href="#cb15-75" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">requires sender_in&lt;Sndr, Env&gt;</code></span></del></span></span>
<span id="cb15-76"><a href="#cb15-76" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">using transform_completion_signatures_of =</code></span></del></span></span>
<span id="cb15-77"><a href="#cb15-77" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">transform_completion_signatures&lt;</code></span></del></span></span>
<span id="cb15-78"><a href="#cb15-78" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env&gt;,</code></span></del></span></span>
<span id="cb15-79"><a href="#cb15-79" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">AdditionalSignatures, SetValue, SetError, SetStopped&gt;;</code></span></del></span></span>
<span id="cb15-80"><a href="#cb15-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-81"><a href="#cb15-81" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [exec.run.loop], run_loop</span></span>
<span id="cb15-82"><a href="#cb15-82" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> run_loop;</span>
<span id="cb15-83"><a href="#cb15-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-84"><a href="#cb15-84" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb15-85"><a href="#cb15-85" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-86"><a href="#cb15-86" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The exposition-only type <code class="sourceCode default"><em><code class="sourceCode default">variant-or-empty</code></em>&lt;Ts...&gt;</code>
is defined as follows <span style="color:blue">… as before</span></p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
For type<span class="rm" style="color: #bf0303"><del>s</del></span>
<code class="sourceCode default">Sndr</code> and <span class="add" style="color: #006e28"><ins>pack of types</ins></span>
<code class="sourceCode default">Env</code>, <span class="add" style="color: #006e28"><ins>let
<span><code class="sourceCode default">CS</code></span> be <span><code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env...&gt;</code></span>.
Then</ins></span> <code class="sourceCode default">single-sender-value-type&lt;Sndr, Env<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span>&gt;</code> is
<span class="add" style="color: #006e28"><ins>ill-formed if
<span><code class="sourceCode default">CS</code></span> is ill-formed or
if
<span><code class="sourceCode default">sizeof...(Env) &gt; 1</code></span>
is <span><code class="sourceCode default">true</code></span>; otherwise,
it is</ins></span> an alias for:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
<code class="sourceCode default"><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">value_types_of_t&lt;Sndr, Env</code></span></del></span></code>
<code class="sourceCode default"><span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">gather-signatures</code></span></em>&lt;set_value_t,
CS</ins></span>, decay_t, type_identity_t&gt;</code> if that type is
well-formed,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Otherwise, <code class="sourceCode default">void</code> if <code class="sourceCode default"><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">value_types_of_t&lt;Sndr, Env</code></span></del></span></code>
<code class="sourceCode default"><span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">gather-signatures</code></span></em>&lt;set_value_t,
CS</ins></span>, tuple, variant&gt;</code> is
<code class="sourceCode default">variant&lt;tuple&lt;&gt;&gt;</code> or
<code class="sourceCode default">variant&lt;&gt;</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
Otherwise, <code class="sourceCode default"><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">value_types_of_t&lt;Sndr, Env</code></span></del></span></code>
<code class="sourceCode default"><span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">gather-signatures</code></span></em>&lt;set_value_t,
CS</ins></span>, <em><code class="sourceCode default">decayed-tuple</code></em>, type_identity_t&gt;</code>
if that type is well-formed,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.4)</a></span>
Otherwise, <code class="sourceCode default"><em><code class="sourceCode default">single-sender-value-type</code></em>&lt;Sndr, Env<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span>&gt;</code> is
ill-formed.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The exposition-only concept
<em><code class="sourceCode default">single-sender</code></em> is
defined as follows:</p>
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env<span class="op">&gt;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">single-sender</code></em> <span class="op">=</span> sender_in<span class="op">&lt;</span>Sndr, Env<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span><span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">{</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        <span class="kw">typename</span> <em><code class="sourceCode default">single-sender-value-type</code></em><span class="op">&lt;</span>Sndr, Env<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span><span class="op">&gt;</span>;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span>;</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<span class="add" style="color: #006e28"><ins>A type satisfies and
models the exposition-only concept
<em><span><code class="sourceCode default">valid-completion-signatures</code></span></em>
if it is a specialization of the
<span><code class="sourceCode default">completion_signatures</code></span>
class template.</ins></span></p>
</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Modify
[exec.snd.general] as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
Subclauses [exec.factories] and [exec.adapt] define customizable
algorithms that return senders. Each algorithm has a default
implementation. Let <code class="sourceCode default">sndr</code> be the
result of an invocation of such an algorithm or an object equal to the
result ([concepts.equality]), and let
<code class="sourceCode default">Sndr</code> be
<code class="sourceCode default">decltype((sndr))</code>. Let
<code class="sourceCode default">rcvr</code> be a receiver of type
<code class="sourceCode default">Rcvr</code> with associated environment
<code class="sourceCode default">env</code> of type
<code class="sourceCode default">Env</code> such that
<code class="sourceCode default">sender_to&lt;Sndr, Rcvr&gt;</code> is
<code class="sourceCode default">true</code>. For the default
implementation of the algorithm that produced
<code class="sourceCode default">sndr</code>, connecting
<code class="sourceCode default">sndr</code> to
<code class="sourceCode default">rcvr</code> and starting the resulting
operation state ([exec.async.ops]) necessarily results in the potential
evaluation ([basic.def.odr]) of a set of completion operations whose
first argument is a subexpression equal to
<code class="sourceCode default">rcvr</code>. Let
<code class="sourceCode default">Sigs</code> be a pack of completion
signatures corresponding to this set of completion operations<span class="rm" style="color: #bf0303"><del>. Then</del></span> <span class="add" style="color: #006e28"><ins>, and let
<span><code class="sourceCode default">CS</code></span> be</ins></span>
the type of the expression <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">get_completion_signatures(sndr, env)</code></span></del></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">get_completion_signatures&lt;Sndr, Env&gt;()</code></span>.
Then
<span><code class="sourceCode default">CS</code></span></ins></span> is
a specialization of the class template
<code class="sourceCode default">completion_signatures</code>
([exec.util.cmplsig]), the set of whose template arguments is
<code class="sourceCode default">Sigs</code>. <span class="add" style="color: #006e28"><ins>If none of the types in
<span><code class="sourceCode default">Sigs</code></span> are dependent
on the type <span><code class="sourceCode default">Env</code></span>,
then the expression <span><code class="sourceCode default">get_completion_signatures&lt;Sndr&gt;()</code></span>
is well-formed and its type is
<span><code class="sourceCode default">CS</code></span>.</ins></span> If
a user-provided implementation of the algorithm that produced
<code class="sourceCode default">sndr</code> is selected instead of the
default: <span class="ednote" style="color: #0000ff">[ Editor&#39;s note:
Reformatted into a list. ]</span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span> Any
completion signature that is in the set of types denoted by <code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env&gt;</code>
and that is not part of <code class="sourceCode default">Sigs</code>
shall correspond to error or stopped completion operations, unless
otherwise specified.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span><span class="add" style="color: #006e28"><ins>If none of the types in
<span><code class="sourceCode default">Sigs</code></span> are dependent
on the type <span><code class="sourceCode default">Env</code></span>,
then <span><code class="sourceCode default">completion_signatures_of_t&lt;Sndr&gt;</code></span>
and <span><code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env&gt;</code></span>
shall denote the same type.</ins></span></p></li>
</ul>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.snd.expos], change para 2 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
For a queryable object <code class="sourceCode default">env</code>,
<code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV</code></em>(env)</code>
is an expression whose type satisfies
<code class="sourceCode default">queryable</code> such that for a query
object <code class="sourceCode default">q</code> and a pack of
subexpressions <code class="sourceCode default">as</code>, the
expression <code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV</code></em>(env).query(q, as...)</code>
is ill-formed if
<code class="sourceCode default">forwarding_query(q)</code> is
<code class="sourceCode default">false</code>; otherwise, it is
expression-equivalent to
<code class="sourceCode default">env.query(q, as...)</code>. <span class="add" style="color: #006e28"><ins>The type
<span><code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)</code></span>
is <span><code class="sourceCode default">decltype(<em><code class="sourceCode default">FWD-ENV</code></em>(declval&lt;Env&gt;()))</code></span>.</ins></span></p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.snd.expos], insert the following paragraph after para 22 and
before para 23 (thus moving the exposition-only concept out of para 24
and into its own para so it can be used from elsewhere): ]</span></p>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
Let
<em><code class="sourceCode default">valid-specialization</code></em> be
the following concept:</p>
<blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>template&lt;template&lt;class...&gt; class T, class... Args&gt;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  concept <em><code class="sourceCode default">valid-specialization</code></em> = requires { typename T&lt;Args...&gt;; }; // exposition only</span></code></pre></div>
</blockquote>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.snd.expos] para 23 add the mandate shown below: ]</span></p>
<blockquote>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Tag, <span class="kw">class</span> Data <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>, <span class="kw">class</span><span class="op">...</span> Child<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">make-sender</code></em><span class="op">(</span>Tag tag, Data<span class="op">&amp;&amp;</span> data, Child<span class="op">&amp;&amp;...</span> child<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">23</a></span>
<em>Mandates</em>: The following expressions are
<code class="sourceCode default">true</code>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.1)</a></span>
<code class="sourceCode default">semiregular&lt;Tag&gt;</code></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.2)</a></span>
<code class="sourceCode default"><em><code class="sourceCode default">movable-value</code></em>&lt;Data&gt;</code></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.3)</a></span>
<code class="sourceCode default">(sender&lt;Child&gt; &amp;&amp;...)</code></p></li>
</ul>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.4)</a></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">dependent_sender&lt;Sndr&gt; || sender_in&lt;Sndr&gt;</code></span>,
where <span><code class="sourceCode default">Sndr</code></span> is
<span><code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>&lt;Tag, Data, Child...&gt;</code></span>
as defined below.</ins></span></p>
<p><em>Recommended practice:</em> When this mandate fails because <code class="sourceCode default">get_completion_signatures&lt;Sndr&gt;()</code>
would exit with an exception, implementations are encouraged to include
information about the exception in the resulting diagnostic.</p></li>
</ul>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.snd.expos] para 24, change the definition of the exposition-only
<em><code class="sourceCode default">basic-sender</code></em> template
as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Returns</em>: A prvalue of type <code class="sourceCode default"><em><code class="sourceCode default">basic-sender</code></em>&lt;Tag, decay_t&lt;Data&gt;, decay_t&lt;Child&gt;...&gt;</code>
that has been direct-list-initialized with the forwarded arguments,
where <em><code class="sourceCode default">basic-sender</code></em> is
the following exposition-only class template except as noted below.</p>
<blockquote>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Tag<span class="op">&gt;</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em><code class="sourceCode default">completion-tag</code></em> <span class="op">=</span> <span class="co">// exposition only</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    same_as<span class="op">&lt;</span>Tag, set_value_t<span class="op">&gt;</span> <span class="op">||</span> same_as<span class="op">&lt;</span>Tag, set_error_t<span class="op">&gt;</span> <span class="op">||</span> same_as<span class="op">&lt;</span>Tag, set_stopped_t<span class="op">&gt;</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;template&lt;class...&gt; class T, class... Args&gt;</code></span></del></span></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">concept <em><code class="sourceCode default">valid-specialization</code></em> = requires { typename T&lt;Args...&gt;; }; // exposition only</code></span></del></span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span>  <span class="co">// exposition only</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-attrs</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-env</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-state</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">start</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template &lt;class Sndr&gt;</code></span></ins></span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">using <em><code class="sourceCode default">data-type</code></em> = decltype(declval&lt;Sndr&gt;().template <em><code class="sourceCode default">get</code></em>&lt;1&gt;());     // exposition only</code></span></ins></span></span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="dt">size_t</span> I <span class="op">=</span> <span class="dv">0</span><span class="op">&gt;</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <em><code class="sourceCode default">child-type</code></em> <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>declval<span class="op">&lt;</span>Sndr<span class="op">&gt;().</span><span class="kw">template</span> <em><code class="sourceCode default">get</code></em><span class="op">&lt;</span>I<span class="op">+</span><span class="dv">2</span><span class="op">&gt;())</span>;     <span class="co">// exposition only</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style:italic">… as before …</span></span>
<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></del></span></span>
<span id="cb19-31"><a href="#cb19-31" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">using <em><code class="sourceCode default">completion-signatures-for</code></em> = <em><code class="sourceCode default">see below</code></em>; // exposition only</code></span></del></span></span>
<span id="cb19-32"><a href="#cb19-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Tag, <span class="kw">class</span> Data, <span class="kw">class</span><span class="op">...</span> Child<span class="op">&gt;</span></span>
<span id="cb19-34"><a href="#cb19-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">basic-sender</code></em> <span class="op">:</span> <em><code class="sourceCode default">product-type</code></em><span class="op">&lt;</span>Tag, Data, Child<span class="op">...&gt;</span> <span class="op">{</span>  <span class="co">// exposition only</span></span>
<span id="cb19-35"><a href="#cb19-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> sender_concept <span class="op">=</span> sender_t;</span>
<span id="cb19-36"><a href="#cb19-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em><code class="sourceCode default">indices-for</code></em> <span class="op">=</span> index_sequence_for<span class="op">&lt;</span>Child<span class="op">...&gt;</span>; <span class="co">// exposition only</span></span>
<span id="cb19-37"><a href="#cb19-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-38"><a href="#cb19-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> get_env<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb19-39"><a href="#cb19-39" aria-hidden="true" tabindex="-1"></a>      <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>_, data, <span class="op">...</span>child<span class="op">]</span> <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb19-40"><a href="#cb19-40" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span>Tag<span class="op">&gt;::</span><em><code class="sourceCode default">get-attrs</code></em><span class="op">(</span>data, child<span class="op">...)</span>;</span>
<span id="cb19-41"><a href="#cb19-41" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-42"><a href="#cb19-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-43"><a href="#cb19-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em><code class="sourceCode default">decays-to</code></em><span class="op">&lt;</span><em><code class="sourceCode default">basic-sender</code></em><span class="op">&gt;</span> Self, receiver Rcvr<span class="op">&gt;</span></span>
<span id="cb19-44"><a href="#cb19-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> <span class="fu">connect</span><span class="op">(</span><span class="kw">this</span> Self<span class="op">&amp;&amp;</span> self, Rcvr rcvr<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em><code class="sourceCode default">see below</code></em><span class="op">)</span></span>
<span id="cb19-45"><a href="#cb19-45" aria-hidden="true" tabindex="-1"></a>      <span class="op">-&gt;</span> <em><code class="sourceCode default">basic-operation</code></em><span class="op">&lt;</span>Self, Rcvr<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb19-46"><a href="#cb19-46" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">{</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Self<span class="op">&gt;(</span>self<span class="op">)</span>, std<span class="op">::</span>move<span class="op">(</span>rcvr<span class="op">)}</span>;</span>
<span id="cb19-47"><a href="#cb19-47" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb19-48"><a href="#cb19-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-49"><a href="#cb19-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em><code class="sourceCode default">decays-to</code></em><span class="op">&lt;</span><em><code class="sourceCode default">basic-sender</code></em><span class="op">&gt;</span> Self, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env<span class="op">&gt;</span></span>
<span id="cb19-50"><a href="#cb19-50" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static constexpr</code></span></ins></span> <span class="kw">auto</span> get_completion_signatures<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">();</code></span></ins></span><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">(this Self&amp;&amp; self, Env&amp;&amp;... env) noexcept</code></span></del></span></span>
<span id="cb19-51"><a href="#cb19-51" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">-&gt; <em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Self, Env...&gt; {</code></span></del></span></span>
<span id="cb19-52"><a href="#cb19-52" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">return {};</code></span></del></span></span>
<span id="cb19-53"><a href="#cb19-53" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">}</code></span></del></span></span>
<span id="cb19-54"><a href="#cb19-54" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb19-55"><a href="#cb19-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.snd.expos], replace para 39 with the paragraphs shown below and
renumber subsequent paragraphs: ]</span></p>
<blockquote>
<div class="rm" style="color: #bf0303">
<p><span class="marginalizedparent"><a class="marginalized">39</a></span> Let
<code class="sourceCode default">Sndr</code> be a (possibly
<code class="sourceCode default">const</code>-qualified) specialization
<em><code class="sourceCode default">basic-sender</code></em> or an
lvalue reference of such, let
<code class="sourceCode default">Rcvr</code> be the type of a receiver
with an associated environment of type
<code class="sourceCode default">Env</code>. If the type <code class="sourceCode default"><em><code class="sourceCode default">basic-operation</code></em>&lt;Sndr, Rcvr&gt;</code>
is well-formed, let <code class="sourceCode default">op</code> be an
lvalue subexpression of that type. Then <code class="sourceCode default"><em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Sndr, Env&gt;</code>
denotes a specialization of
<code class="sourceCode default">completion_signatures</code>, the set
of whose template arguments corresponds to the set of completion
operations that are potentially evaluated ([basic.def.odr]) as a result
of evaluating <code class="sourceCode default">op.start()</code>.
Otherwise, <code class="sourceCode default"><em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Sndr, Env&gt;</code>
is ill-formed. If <code class="sourceCode default"><em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Sndr, Env&gt;</code>
is well-formed and its type is not dependent upon the type
<code class="sourceCode default">Env</code>, <code class="sourceCode default"><em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Sndr&gt;</code>
is well-formed and denotes the same type; otherwise, <code class="sourceCode default"><em><code class="sourceCode default">completion-signatures-for</code></em>&lt;Sndr&gt;</code>
is ill-formed.</p>
</div>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb20"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>template &lt;class Sndr, class... Env&gt;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  static consteval void <em><code class="sourceCode default">default-impls</code></em>::<em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
Let <code class="sourceCode default">Is</code> be the pack of integral
template arguments of the
<code class="sourceCode default">integer_sequence</code> specialization
denoted by
<code class="sourceCode default"><em><code class="sourceCode default">indices-for</code></em>&lt;Sndr&gt;</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>(get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr, Is&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;(), ...)</span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Remarks</em>: For any types
<code class="sourceCode default">T</code>,
<code class="sourceCode default">S</code>, and pack
<code class="sourceCode default">E</code>, let
<code class="sourceCode default">e</code> be the expression <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;T&gt;::<em><code class="sourceCode default">check-types</code></em>&lt;S, E...&gt;()</code>.
Then exactly one of the following is
<code class="sourceCode default">true</code>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<code class="sourceCode default">e</code> is ill-formed, or</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.3)</a></span> The
evaluation of <code class="sourceCode default">e</code> exits with an
exception, or</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.2)</a></span>
<code class="sourceCode default">e</code> is a core constant
expression.</p></li>
</ul>
<p>When <code class="sourceCode default">e</code> is a core constant
expression, the types <code class="sourceCode default">S</code>,
<code class="sourceCode default">E...</code> uniquely determine a set of
completion signatures.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Tag, class Data, class... Child&gt;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  template &lt;class Sndr, class... Env&gt;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    constexpr auto <em><code class="sourceCode default">basic-sender</code></em>&lt;Tag, Data, Child...&gt;::get_completion_signatures();</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
Let <code class="sourceCode default">Rcvr</code> be the type of a
receiver whose environment has type
<code class="sourceCode default">E</code>, where
<code class="sourceCode default">E</code> is the first type in the list
<code class="sourceCode default">Env..., env&lt;&gt;</code>. Let
<code class="sourceCode default"><em><code class="sourceCode default">CHECK-TYPES</code></em>()</code>
be the expression <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;Tag&gt;::template <em><code class="sourceCode default">check-types</code></em>&lt;Sndr, E&gt;()</code>,
and let <code class="sourceCode default">CS</code> be a type determined
as follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span> If
<code class="sourceCode default"><em><code class="sourceCode default">CHECK-TYPES</code></em>()</code>
is a core constant expression, let
<code class="sourceCode default">op</code> be an lvalue subexpression
whose type is <code class="sourceCode default">connect_result_t&lt;Sndr,   Rcvr&gt;</code>.
Then <code class="sourceCode default">CS</code> is the specialization of
<code class="sourceCode default">completion_signatures</code> the set of
whose template arguments correspond to the set of completion operations
that are potentially evaluated ([basic.def.odr]) as a result of
evaluating <code class="sourceCode default">op.start()</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.2)</a></span>
Otherwise, <code class="sourceCode default">CS</code> is
<code class="sourceCode default">completion_signatures&lt;&gt;</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Constraints</em>:
<code class="sourceCode default"><em><code class="sourceCode default">CHECK-TYPES</code></em>()</code>
is a well-formed expression.</p>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Effects</em>: Equivalent to</p>
<blockquote>
<div class="sourceCode" id="cb23"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><em><code class="sourceCode default">CHECK-TYPES</code></em>();</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>return CS();</span></code></pre></div>
</blockquote>

</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Add the
following new paragraphs to the end of [exec.snd.expos] ]</span></p>
<blockquote>
<div class="add" style="color: #006e28">

<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb24"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>template&lt;class... Fns&gt;</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>struct <em><code class="sourceCode default">overload-set</code></em> : Fns... {</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  using Fns::operator()...;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
following is moved from [exec.on] para 6 and modified. ]</span></p>
<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb25"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>struct <em><code class="sourceCode default">not-a-sender</code></em> {</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>  using sender_concept = sender_t;</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>  template&lt;class Sndr&gt;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>  static constexpr auto get_completion_signatures() -&gt; completion_signatures&lt;&gt; {</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>    throw <em>unspecified</em>;</span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</div>
<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb26"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>constexpr void <em><code class="sourceCode default">decay-copyable-result-datums(auto cs)</code></em> {</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  cs.<em><code class="sourceCode default">for-each</code></em>([]&lt;class Tag, class... Ts&gt;(Tag(*)(Ts...)) {</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    if constexpr (!(is_constructible_v&lt;decay_t&lt;Ts&gt;, Ts&gt; &amp;&amp;...))</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>      throw <em><code class="sourceCode default">unspecified</code></em>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>  });</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>

</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.snd.concepts] para 1 and add a new para after 1 as follows:
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The <code class="sourceCode default">sender</code> concept <span style="color:blue;font-style:italic">… as before …</span> to produce an
operation state.</p>
<blockquote>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sigs&gt;</code></span></del></span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">concept <em><code class="sourceCode default">valid-completion-signatures</code></em> = <em><code class="sourceCode default">see below</code></em>;            // exposition only</code></span></del></span></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;auto&gt;</code></span></ins></span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept <em><code class="sourceCode default">is-constant</code></em> = true;</code></span></ins></span>                                 <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">// exposition only</code></span></ins></span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">is-sender</code></em> <span class="op">=</span>                                         <span class="co">// exposition only</span></span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>      derived_from<span class="op">&lt;</span><span class="kw">typename</span> Sndr<span class="op">::</span>sender_concept, sender_t<span class="op">&gt;</span>;</span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em><code class="sourceCode default">enable-sender</code></em> <span class="op">=</span>                                     <span class="co">// exposition only</span></span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a>      <em><code class="sourceCode default">is-sender</code></em><span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">||</span></span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a>      <em><code class="sourceCode default">is-awaitable</code></em><span class="op">&lt;</span>Sndr, <em><code class="sourceCode default">env-promise</code></em><span class="op">&lt;</span>env<span class="op">&lt;&gt;&gt;&gt;</span>;                   <span class="co">// [exec.awaitable]</span></span>
<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-17"><a href="#cb27-17" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr&gt;</code></span></ins></span></span>
<span id="cb27-18"><a href="#cb27-18" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">consteval bool <em><code class="sourceCode default">is-dependent-sender-helper</code></em>() try {</code></span></ins></span>           <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">// exposition only</code></span></ins></span></span>
<span id="cb27-19"><a href="#cb27-19" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">get_completion_signatures&lt;Sndr&gt;();</code></span></ins></span></span>
<span id="cb27-20"><a href="#cb27-20" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">return false;</code></span></ins></span></span>
<span id="cb27-21"><a href="#cb27-21" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">} catch (dependent_sender_error&amp;) {</code></span></ins></span></span>
<span id="cb27-22"><a href="#cb27-22" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">return true;</code></span></ins></span></span>
<span id="cb27-23"><a href="#cb27-23" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">}</code></span></ins></span></span>
<span id="cb27-24"><a href="#cb27-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-25"><a href="#cb27-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr<span class="op">&gt;</span></span>
<span id="cb27-26"><a href="#cb27-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> sender <span class="op">=</span></span>
<span id="cb27-27"><a href="#cb27-27" aria-hidden="true" tabindex="-1"></a>      <span class="dt">bool</span><span class="op">(</span><em><code class="sourceCode default">enable-sender</code></em><span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>Sndr<span class="op">&gt;&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-28"><a href="#cb27-28" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> remove_cvref_t<span class="op">&lt;</span>Sndr<span class="op">&gt;&amp;</span> sndr<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-29"><a href="#cb27-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> get_env<span class="op">(</span>sndr<span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> <em><code class="sourceCode default">queryable</code></em>;</span>
<span id="cb27-30"><a href="#cb27-30" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-31"><a href="#cb27-31" aria-hidden="true" tabindex="-1"></a>      move_constructible<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>Sndr<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-32"><a href="#cb27-32" aria-hidden="true" tabindex="-1"></a>      constructible_from<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>Sndr<span class="op">&gt;</span>, Sndr<span class="op">&gt;</span>;</span>
<span id="cb27-33"><a href="#cb27-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-34"><a href="#cb27-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Env <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">= env&lt;&gt;</code></span></del></span><span class="op">&gt;</span></span>
<span id="cb27-35"><a href="#cb27-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> sender_in <span class="op">=</span></span>
<span id="cb27-36"><a href="#cb27-36" aria-hidden="true" tabindex="-1"></a>      sender<span class="op">&lt;</span>Sndr<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-37"><a href="#cb27-37" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">(sizeof...(Env) &lt;= 1) &amp;&amp;</code></span></ins></span></span>
<span id="cb27-38"><a href="#cb27-38" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">(</code></span></ins></span>queryable<span class="op">&lt;</span>Env<span class="op">&gt;</span> <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&amp;&amp;...)</code></span></ins></span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-39"><a href="#cb27-39" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">is-constant</code></em>&lt;get_completion_signatures&lt;Sndr, Env...&gt;()&gt;;</code></span></ins></span></span>
<span id="cb27-40"><a href="#cb27-40" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">requires (Sndr&amp;&amp; sndr, Env&amp;&amp; env) {</code></span></del></span></span>
<span id="cb27-41"><a href="#cb27-41" aria-hidden="true" tabindex="-1"></a>        <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">{ get_completion_signatures(std::forward&lt;Sndr&gt;(sndr), std::forward&lt;Env&gt;(env)) }</code></span></del></span></span>
<span id="cb27-42"><a href="#cb27-42" aria-hidden="true" tabindex="-1"></a>          <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">-&gt; <em><code class="sourceCode default">valid-completion-signatures</code></em>;</code></span></del></span></span>
<span id="cb27-43"><a href="#cb27-43" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">};</code></span></del></span></span>
<span id="cb27-44"><a href="#cb27-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-45"><a href="#cb27-45" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr&gt;</code></span></ins></span></span>
<span id="cb27-46"><a href="#cb27-46" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept dependent_sender =</code></span></ins></span></span>
<span id="cb27-47"><a href="#cb27-47" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">sender&lt;Sndr&gt; &amp;&amp; bool_constant&lt;<em><code class="sourceCode default">is-dependent-sender-helper</code></em>&lt;Sndr&gt;()&gt;::value;</code></span></ins></span></span>
<span id="cb27-48"><a href="#cb27-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-49"><a href="#cb27-49" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;</span></span>
<span id="cb27-50"><a href="#cb27-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> sender_to <span class="op">=</span></span>
<span id="cb27-51"><a href="#cb27-51" aria-hidden="true" tabindex="-1"></a>      sender_in<span class="op">&lt;</span>Sndr, env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-52"><a href="#cb27-52" aria-hidden="true" tabindex="-1"></a>      receiver_of<span class="op">&lt;</span>Rcvr, completion_signatures_of_t<span class="op">&lt;</span>Sndr, env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb27-53"><a href="#cb27-53" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Rcvr<span class="op">&amp;&amp;</span> rcvr<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-54"><a href="#cb27-54" aria-hidden="true" tabindex="-1"></a>        <span class="fu">connect</span><span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Sndr<span class="op">&gt;(</span>sndr<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Rcvr<span class="op">&gt;(</span>rcvr<span class="op">))</span>;</span>
<span id="cb27-55"><a href="#cb27-55" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span>;</span>
<span id="cb27-56"><a href="#cb27-56" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<div class="add" style="color: #006e28">

<ul>
<li><span class="marginalizedparent"><a class="marginalized">?</a></span> <span class="add" style="color: #006e28"><ins>For a type
<span><code class="sourceCode default">Sndr</code></span>, if
<span><code class="sourceCode default">sender&lt;Sndr&gt;</code></span>
is <span><code class="sourceCode default">true</code></span> and
<span><code class="sourceCode default">dependent_sender&lt;Sndr&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>, then
<span><code class="sourceCode default">Sndr</code></span> is a
non-dependent sender ([exec.async.ops]).</ins></span></li>
</ul>

</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Strike
[exec.snd.concepts] para 3 (this para is moved to [execution.syn]):
]</span></p>
<div class="rm" style="color: #bf0303">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<span class="rm" style="color: #bf0303"><del>A type models the
exposition-only concept
<em><span><code class="sourceCode default">valid-completion-signatures</code></span></em>
if it denotes a specialization of the
<span><code class="sourceCode default">completion_signatures</code></span>
class template.</del></span></p>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.snd.concepts] para 4 as follows (so that the exposition-only
<em><code class="sourceCode default">sender-of</code></em> concept tests
for sender-ness with no environment as opposed to the empty environment,
<code class="sourceCode default">env&lt;&gt;</code>): ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The exposition-only concepts
<em><code class="sourceCode default">sender-of</code></em> and
<em><code class="sourceCode default">sender-in-of</code></em> define the
requirements for a sender type that completes with a given unique set of
value result types.</p>
<blockquote>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> As<span class="op">&gt;</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em><code class="sourceCode default">value-signature</code></em> <span class="op">=</span> set_value_t<span class="op">(</span>As<span class="op">...)</span>;      <span class="co">// exposition only</span></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sndr, class Env, class... Values&gt;</code></span></del></span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">concept <em><code class="sourceCode default">sender-in-of</code></em> =</code></span></del></span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">sender_in&lt;Sndr, Env&gt; &amp;&amp;</code></span></del></span></span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>      <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">MATCHING-SIG</code></em>(                     // see [exec.general]</code></span></del></span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>        <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">set_value_t(Values...),</code></span></del></span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>        <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">value_types_of_t&lt;Sndr, Env, <em><code class="sourceCode default">value-signature</code></em>, type_identity_t&gt;);</code></span></del></span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sndr, class... Values&gt;</code></span></del></span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">concept <em><code class="sourceCode default">sender-of</code></em> = <em><code class="sourceCode default">sender-in-of</code></em>&lt;Sndr, env&lt;&gt;, Values...&gt;;</code></span></del></span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class SetValue, class... Env&gt;</code></span></ins></span></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept <em><code class="sourceCode default">sender-in-of-impl</code></em> =         // exposition only</code></span></ins></span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">sender_in&lt;Sndr, Env...&gt; &amp;&amp;</code></span></ins></span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">MATCHING-SIG</code></em>(SetValue,                          // see [exec.general]</code></span></ins></span></span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a>                   <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">gather-signatures</code></em>&lt;set_value_t,     // see [exec.util.cmplsig]</code></span></ins></span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a>                                     <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env...&gt;,</code></span></ins></span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>                                     <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">value-signature</code></em>,</code></span></ins></span></span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>                                     <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">type_identity_t&gt;);</code></span></ins></span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class Env, class... Values&gt;</code></span></ins></span></span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept <em><code class="sourceCode default">sender-in-of</code></em> =              // exposition only</code></span></ins></span></span>
<span id="cb28-26"><a href="#cb28-26" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">sender-in-of-impl</code></em>&lt;Sndr, set_value_t(Values...), Env&gt;;</code></span></ins></span></span>
<span id="cb28-27"><a href="#cb28-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-28"><a href="#cb28-28" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Values&gt;</code></span></ins></span></span>
<span id="cb28-29"><a href="#cb28-29" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">concept <em><code class="sourceCode default">sender-of</code></em> =                 // exposition only</code></span></ins></span></span>
<span id="cb28-30"><a href="#cb28-30" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">sender-in-of-impl</code></em>&lt;Sndr, set_value_t(Values...)&gt;;</code></span></ins></span></span>
<span id="cb28-31"><a href="#cb28-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.awaitable] p 1-4 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The sender concepts recognize awaitables as senders. For [exec], an
<em>awaitable</em> is an expression that would be well-formed as the
operand of a <code class="sourceCode default">co_await</code> expression
within a given context.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
For a subexpression <code class="sourceCode default">c</code>, let
<code class="sourceCode default">GET-AWAITER(c, p)</code> be
expression-equivalent to the series of transformations and conversions
applied to <code class="sourceCode default">c</code> as the operand of
an <em>await-expression</em> in a coroutine, resulting in lvalue
<code class="sourceCode default">e</code> as described by [expr.await],
where <code class="sourceCode default">p</code> is an lvalue referring
to the coroutine’s promise, which has type
<code class="sourceCode default">Promise</code>.</p>
<p>[<em>Note 1</em>: This includes the invocation of the promise type’s
<code class="sourceCode default">await_transform</code> member if any,
the invocation of the
<code class="sourceCode default">operator co_await</code> picked by
overload resolution if any, and any necessary implicit conversions and
materializations. – <em>end note</em>]</p>
<p><span class="add" style="color: #006e28"><ins>Let
<span><code class="sourceCode default">GET-AWAITER(c)</code></span> be
expression-equivalent to
<span><code class="sourceCode default">GET-AWAITER(c, q)</code></span>
where <span><code class="sourceCode default">q</code></span> is an
lvalue of an unspecified empty class type
<em><span><code class="sourceCode default">none-such</code></span></em>
that lacks an
<span><code class="sourceCode default">await_transform</code></span>
member, and where <span><code class="sourceCode default">coroutine_handle&lt;<em><code class="sourceCode default">none-such</code></em>&gt;</code></span>
behaves as
<span><code class="sourceCode default">coroutine_handle&lt;void&gt;</code></span>.</ins></span></p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
Let <em><code class="sourceCode default">is-awaitable</code></em> be the
following exposition-only concept: <span class="ednote" style="color: #0000ff">[ Editor&#39;s note: NB: there are added ellipses in
the following code block. ]</span></p>
<blockquote>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em><code class="sourceCode default">await-suspend-result</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> A, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Promise<span class="op">&gt;</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em><code class="sourceCode default">is-awaiter</code></em> <span class="op">=</span> <span class="co">// exposition only</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>     <span class="kw">requires</span> <span class="op">(</span>A<span class="op">&amp;</span> a, coroutine_handle<span class="op">&lt;</span>Promise<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span><span class="op">&gt;</span> h<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>        a<span class="op">.</span>await_ready<span class="op">()</span> <span class="op">?</span> <span class="dv">1</span> <span class="op">:</span> <span class="dv">0</span>;</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> a<span class="op">.</span>await_suspend<span class="op">(</span>h<span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> <em><code class="sourceCode default">await-suspend-result</code></em>;</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>        a<span class="op">.</span>await_resume<span class="op">()</span>;</span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a>     <span class="op">}</span>;</span>
<span id="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> C, class<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> Promise<span class="op">&gt;</span></span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em><code class="sourceCode default">is-awaitable</code></em> <span class="op">=</span></span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>     <span class="kw">requires</span> <span class="op">(</span>C <span class="op">(*</span>fc<span class="op">)()</span> <span class="kw">noexcept</span>, Promise<span class="op">&amp;</span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span> p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <em><code class="sourceCode default">GET-AWAITER</code></em><span class="op">(</span>fc<span class="op">()</span>, p<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span><span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> <em><code class="sourceCode default">is-awaiter</code></em><span class="op">&lt;</span>Promise<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">...</code></span></ins></span><span class="op">&gt;</span>;</span>
<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a>     <span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p><code class="sourceCode default"><em><code class="sourceCode default">await-suspend-result</code></em>&lt;T&gt;</code>
is <code class="sourceCode default">true</code> if and only if one of
the following is <code class="sourceCode default">true</code>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>
<code class="sourceCode default">T</code> is
<code class="sourceCode default">void</code>, or</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>
<code class="sourceCode default">T</code> is
<code class="sourceCode default">bool</code>, or</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.3)</a></span>
<code class="sourceCode default">T</code> is a specialization of
<code class="sourceCode default">coroutine_handle</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
For a subexpression <code class="sourceCode default">c</code> such that
<code class="sourceCode default">decltype((c))</code> is type
<code class="sourceCode default">C</code>, and an lvalue
<code class="sourceCode default">p</code> of type
<code class="sourceCode default">Promise</code>, <code class="sourceCode default"><em><code class="sourceCode default">await-result-type</code></em>&lt;C, Promise&gt;</code>
denotes the type <code class="sourceCode default">decltype(<em><code class="sourceCode default">GET-AWAITER</code></em>(c, p).await_resume())</code>
<span class="add" style="color: #006e28"><ins>and
<span><code class="sourceCode default"><em><code class="sourceCode default">await-result-type</code></em>&lt;C&gt;</code></span>
denotes the type <span><code class="sourceCode default">decltype(<em><code class="sourceCode default">GET-AWAITER</code></em>(c).await_resume())</code></span></ins></span>.</p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.getcomplsigs] as follows: ]</span></p>
<blockquote>
<div class="rm" style="color: #bf0303">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">get_completion_signatures</code> is a
customization point object. Let
<code class="sourceCode default">sndr</code> be an expression such that
<code class="sourceCode default">decltype((sndr))</code> is
<code class="sourceCode default">Sndr</code>, and let
<code class="sourceCode default">env</code> be an expression such that
<code class="sourceCode default">decltype((env))</code> is
<code class="sourceCode default">Env</code>. Let
<code class="sourceCode default">new_sndr</code> be the expression <code class="sourceCode default">transform_sender(decltype(<em><code class="sourceCode default">get-domain-late</code></em>(sndr, env)){}, sndr, env)</code>,
and let <code class="sourceCode default">NewSndr</code> be
<code class="sourceCode default">decltype((new_sndr))</code>. Then <code class="sourceCode default">get_completion_signatures(sndr, env)</code>
is expression-equivalent to
<code class="sourceCode default">(void(sndr), void(env), CS())</code>
except that <code class="sourceCode default">void(sndr)</code> and
<code class="sourceCode default">void(env)</code> are indeterminately
sequenced, where <code class="sourceCode default">CS</code> is:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span>
<code class="sourceCode default">decltype(new_sndr.get_completion_signatures(env))</code>
if that type is well-formed,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
Otherwise, <code class="sourceCode default">remove_cvref_t&lt;NewSndr&gt;​::​completion_signatures</code>
if that type is well-formed,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
Otherwise, if <code class="sourceCode default"><em><code class="sourceCode default">is-awaitable</code></em>&lt;NewSndr, <em><code class="sourceCode default">env-promise</code></em>&lt;Env&gt;&gt;</code>
is <code class="sourceCode default">true</code>, then:</p></li>
</ul>
<blockquote>
<div class="sourceCode" id="cb30"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>completion_signatures&lt;</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">SET-VALUE-SIG</code></em>(<em><code class="sourceCode default">await-result-type</code></em>&lt;NewSndr, <em><code class="sourceCode default">env-promise</code></em>&lt;Env&gt;&gt;),        //  ([exec.snd.concepts])</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>  set_error_t(exception_ptr),</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>  set_stopped_t()&gt;</span></code></pre></div>
</blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
Otherwise, <code class="sourceCode default">CS</code> is
ill-formed.</li>
</ul>

</div>
</blockquote>
<blockquote>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb31"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>template &lt;class Sndr, class... Env&gt;</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>  consteval auto get_completion_signatures() -&gt; <code class="sourceCode default"><em><code class="sourceCode default">valid-completion-signatures</code></em> auto</code>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
Let <em><code class="sourceCode default">except</code></em> be an rvalue
subexpression of an unspecified class type
<em><code class="sourceCode default">Except</code></em> such that <code class="sourceCode default">move_constructible&lt;Except&gt; &amp;&amp; derived_from&lt;Except, exception&gt;</code>
is <code class="sourceCode default">true</code>. Let
<code class="sourceCode default"><em><code class="sourceCode default">CHECKED-COMPLSIGS</code></em>(<em><code class="sourceCode default">e</code></em>)</code>
be <em><code class="sourceCode default">e</code></em> if
<em><code class="sourceCode default">e</code></em> is a core constant
expression whose type satisfies
<em><code class="sourceCode default">valid-completion-signatures</code></em>;
otherwise, it is the following expression:</p>
<blockquote>
<div class="sourceCode" id="cb32"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a>(<em><code class="sourceCode default">e</code></em>, throw <em><code class="sourceCode default">except</code></em>, completion_signatures())</span></code></pre></div>
</blockquote>
<p>Let <code class="sourceCode default"><em><code class="sourceCode default">get-complsigs</code></em>&lt;Sndr, Env...&gt;()</code>
be expression-equivalent to <code class="sourceCode default">remove_reference_t&lt;Sndr&gt;::template get_completion_signatures&lt;Sndr, Env...&gt;()</code>,
and let <code class="sourceCode default">NewSndr</code> be
<code class="sourceCode default">Sndr</code> if
<code class="sourceCode default">sizeof...(Env) == 0</code> is
<code class="sourceCode default">true</code>; otherwise,
<code class="sourceCode default">decltype(<em><code class="sourceCode default">s</code></em>)</code>
where <em><code class="sourceCode default">s</code></em> is the
following expression:</p>
<blockquote>
<div class="sourceCode" id="cb33"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>transform_sender(</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">get-domain-late</code></em>(declval&lt;Sndr&gt;(), declval&lt;Env&gt;()...),</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>  declval&lt;Sndr&gt;(),</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>  declval&lt;Env&gt;()...)</span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Constraints</em>:
<code class="sourceCode default">sizeof...(Env) &lt;= 1</code> is
<code class="sourceCode default">true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Effects</em>: Equivalent to:
<code class="sourceCode default">return <em>e</em>;</code> where
<em><code class="sourceCode default">e</code></em> is
expression-equivalent to the following:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<code class="sourceCode default"><em><code class="sourceCode default">CHECKED-COMPLSIGS</code></em>(<em><code class="sourceCode default">get-complsigs</code></em>&lt;NewSndr, Env...&gt;())</code>
if <code class="sourceCode default"><em><code class="sourceCode default">get-complsigs</code></em>&lt;NewSndr, Env...&gt;()</code>
is a well-formed expression.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.2)</a></span>
Otherwise, <code class="sourceCode default"><em><code class="sourceCode default">CHECKED-COMPLSIGS</code></em>(<em><code class="sourceCode default">get-complsigs</code></em>&lt;NewSndr&gt;())</code>
if <code class="sourceCode default"><em><code class="sourceCode default">get-complsigs</code></em>&lt;NewSndr&gt;()</code>
is a well-formed expression.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.3)</a></span>
Otherwise,</p>
<blockquote>
<div class="sourceCode" id="cb34"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>completion_signatures&lt;</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">SET-VALUE-SIG</code></em>(<em><code class="sourceCode default">await-result-type</code></em>&lt;NewSndr, <em><code class="sourceCode default">env-promise</code></em>&lt;Env&gt;...&gt;),  //  ([exec.snd.concepts])</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  set_error_t(exception_ptr),</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a>  set_stopped_t()&gt;</span></code></pre></div>
</blockquote>
<p>if <code class="sourceCode default"><em><code class="sourceCode default">is-awaitable</code></em>&lt;NewSndr, <em><code class="sourceCode default">env-promise</code></em>&lt;Env&gt;...&gt;</code>
is <code class="sourceCode default">true</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.4)</a></span>
Otherwise, <code class="sourceCode default">(throw <em><code class="sourceCode default">dependent-sender-error</code></em>(), completion_signatures())</code>
if <code class="sourceCode default">sizeof...(Env) == 0</code> is
<code class="sourceCode default">true</code>, where
<em><code class="sourceCode default">dependent-sender-error</code></em>
is <code class="sourceCode default">dependent_sender_error</code> or an
unspecified type derived publicly and unambiguously from
<code class="sourceCode default">dependent_sender_error</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.5)</a></span>
Otherwise, <code class="sourceCode default">(throw <em><code class="sourceCode default">except</code></em>, completion_signatures())</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
Given a type <code class="sourceCode default">Env</code>, if <code class="sourceCode default">completion_signatures_of_t&lt;Sndr&gt;</code>
and <code class="sourceCode default">completion_signatures_of_t&lt;Sndr, Env&gt;</code>
are both well-formed, they shall denote the same type.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Let <code class="sourceCode default">rcvr</code> be an rvalue whose type
<span class="ednote" style="color: #0000ff">[ Editor&#39;s note: ... as
before ]</span>.</p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: At the
very bottom of [exec.connect], change the <em>Mandates</em> of para 6 as
follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The expression
<code class="sourceCode default">connect(sndr, rcvr)</code> is
expression-equivalent to:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span>
<code class="sourceCode default">new_sndr.connect(rcvr)</code> if that
expression is well-formed.</p>
<p><em>Mandates</em>: The type of the expression above satisfies
<code class="sourceCode default">operation_state</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span>
Otherwise, <code class="sourceCode default"><em><code class="sourceCode default">connect-awaitable</code></em>(new_sndr, rcvr)</code>.</p></li>
</ul>
<p><em>Mandates</em>: <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">sender&lt;Sndr&gt; &amp;&amp; receiver&lt;Rcvr&gt;</code></span></del></span>
<span class="add" style="color: #006e28"><ins>The following are
<span><code class="sourceCode default">true</code></span>:</ins></span></p>
<div class="add" style="color: #006e28">

<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.3)</a></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">sender_in&lt;Sndr, env_of_t&lt;Rcvr&gt;&gt;</code></span></ins></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.4)</a></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">receiver_of&lt;Rcvr, completion_signatures_of_t&lt;Sndr, env_of_t&lt;Rcvr&gt;&gt;&gt;</code></span></ins></span></p></li>
</ul>

</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: In
[exec.read.env] para 3, make the following change: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<code class="sourceCode default">read_env</code> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span><em><code class="sourceCode default">decayed-typeof</code></em><span class="op">&lt;</span>read_env<span class="op">&gt;&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">start</code></em> <span class="op">=</span></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>      <span class="op">[](</span><span class="kw">auto</span> query, <span class="kw">auto</span><span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>        <em><code class="sourceCode default">TRY-SET-VALUE</code></em><span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>rcvr<span class="op">)</span>, query<span class="op">(</span>get_env<span class="op">(</span>rcvr<span class="op">)))</span>;</span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span>;</span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class Env&gt;</code></span></ins></span></span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb36"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class Env&gt;</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>static consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span> Let
<code class="sourceCode default">Q</code> be <code class="sourceCode default">decay_t&lt;<em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;&gt;</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>
<em>Throws</em>: An exception of an unspecified type derived from
<code class="sourceCode default">exception</code> if the expression
<code class="sourceCode default">Q()(env)</code> is ill-formed or has
type <code class="sourceCode default">void</code>, where
<code class="sourceCode default">env</code> is an lvalue subexpression
whose type is <code class="sourceCode default">Env</code>.</p></li>
</ul>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.adapt.general] as follows: ]</span></p>
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.4)</a></span> When
a parent sender is connected to a receiver
<code class="sourceCode default">rcvr</code>, any receiver used to
connect a child sender has an associated environment equal to
<code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV</code></em>(get_env(rcvr))</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.?)</a></span>
<span class="add" style="color: #006e28"><ins>An adaptor whose child
senders are all non-dependent ([async.ops]) is itself
non-dependent.</ins></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.5)</a></span>
These requirements apply to any function that is selected by the
implementation of the sender adaptor.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.?)</a></span>
<span class="add" style="color: #006e28"><ins><em>Recommended
practice</em>: Implementors are encouraged to use the completion
signatures of the adaptors to communicate type errors to users and to
propagate any such type errors from child senders.</ins></span></p></li>
</ul>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.write.env] as follows (see <span class="citation" data-cites="P3284R4">[<a href="#ref-P3284R4" role="doc-biblioref">P3284R4</a>]</span> for [exec.write.env], to be
voted on in Bulgaria): ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">write_env</code> is a sender adaptor
that accepts a sender and a queryable object, and that returns a sender
that, when connected with a receiver
<code class="sourceCode default">rcvr</code>, connects the adapted
sender with a receiver whose execution environment is the result of
joining the queryable argument
<code class="sourceCode default">env</code> to the result of
<code class="sourceCode default">get_env(rcvr)</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<code class="sourceCode default">write_env</code> is a customization
point object. For some subexpressions
<code class="sourceCode default">sndr</code> and
<code class="sourceCode default">env</code>, if
<code class="sourceCode default">decltype((sndr))</code> does not
satisfy <code class="sourceCode default">sender</code> or if
<code class="sourceCode default">decltype((env))</code> does not satisfy
<em><code class="sourceCode default">queryable</code></em>, the
expression <code class="sourceCode default">write_env(sndr, env)</code>
is ill-formed. Otherwise, it is expression-equivalent to
<code><i>make-sender</i>(write_env, env, sndr)</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
Let <em><code class="sourceCode default">write-env-t</code></em> denote
the type
<code class="sourceCode default">decltype(auto(write_env))</code>. The
exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.expos]) is specialized for
<em><code class="sourceCode default">write-env-t</code></em> as
follows:</p>
<blockquote>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span><em><code class="sourceCode default">write-env-t</code></em><span class="op">&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static constexpr auto <em><code class="sourceCode default">join-env</code></em>(const auto&amp; state, const auto&amp; env) noexcept {</code></span></ins></span></span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">return <em><code class="sourceCode default">see below</code></em>;</code></span></ins></span></span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">}</code></span></ins></span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-env</code></em> <span class="op">=</span></span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="kw">auto</span>, <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> state, <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">see below</code></em></code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">join-env</code></em>(state, <em><code class="sourceCode default">FWD-ENV</code></em>(get_env(rcvr)))</code></span></ins></span>;</span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a>  <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>Invocation of <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;<em><code class="sourceCode default">write-env-t</code></em>&gt;::<em><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">get-env</code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">join-env</code></span></ins></span></em></code>
returns an object <code class="sourceCode default">e</code> such
that</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>
<code class="sourceCode default">decltype(e)</code> models
<em><code class="sourceCode default">queryable</code></em> and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>
given a query object <code class="sourceCode default">q</code>, the
expression <code class="sourceCode default">e.query(q)</code> is
expression-equivalent to
<code class="sourceCode default">state.query(q)</code> if that
expression is valid; otherwise,
<code class="sourceCode default">e.query(q)</code> is
expression-equivalent to <code class="sourceCode default"><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em>FWD-ENV</em>(get_env(rcvr))</code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">env</code></span></ins></span>.query(q)</code>.</p></li>
</ul>
<div class="add" style="color: #006e28">

<ul>
<li><span class="marginalizedparent"><a class="marginalized">(3.3)</a></span>
<span class="add" style="color: #006e28"><ins>For type
<span><code class="sourceCode default">Sndr</code></span> and pack of
types <span><code class="sourceCode default">Env</code></span>, let
<span><code class="sourceCode default">State</code></span> be
<span><code class="sourceCode default"><em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;</code></span>
and let <span><code class="sourceCode default">JoinEnv</code></span> be
the pack <span><code class="sourceCode default">decltype(<em><code class="sourceCode default">join-env</code></em>(declval&lt;State&gt;(), <em><code class="sourceCode default">FWD-ENV</code></em>(declval&lt;Env&gt;())))</code></span>.
Then <span><code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;<em><code class="sourceCode default">write-env-t</code></em>&gt;::<em><code class="sourceCode default">check-types</code></em>&lt;Sndr, Env...&gt;()</code></span>
is expression-equivalent to <span><code class="sourceCode default">get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, JoinEnv...&gt;()</code></span>.</ins></span></li>
</ul>

</div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.schedule.from] para 4 and insert a new para between 6 and 7 as
follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<code class="sourceCode default">schedule_from_t</code> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span>schedule_from_t<span class="op">&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-attrs</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below;</code></em></span>
<span id="cb38-5"><a href="#cb38-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-state</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below;</code></em></span>
<span id="cb38-6"><a href="#cb38-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below;</code></em></span>
<span id="cb38-7"><a href="#cb38-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb38-8"><a href="#cb38-8" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb38-9"><a href="#cb38-9" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb38-10"><a href="#cb38-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb38-11"><a href="#cb38-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
The member <span style="color:blue;font-style=italic">… as before
…</span></p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;schedule_from_t&gt;::<em><code class="sourceCode default">get-state</code></em></code>
is initialized with a callable object equivalent to the following
lambda: <span class="ednote" style="color: #0000ff">[ Editor&#39;s note:
This integrates the resolution from <a href="https://cplusplus.github.io/LWG/issue4203">LWG#4203</a>.
]</span></p>
<blockquote>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="op">[]&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Rcvr<span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span>see below<span class="op">)</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> sender_in<span class="op">&lt;</span>child<span class="op">-</span>type<span class="op">&lt;</span>Sndr<span class="op">&gt;</span>, <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV-T</code></em>(</code></span></ins></span>env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;</span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span><span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>_, sch, child<span class="op">]</span> <span class="op">=</span> sndr;</span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style=italic">… as before …</span></span></code></pre></div>
</blockquote>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb40"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class... Env&gt;</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>static consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb41"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>get_completion_signatures&lt;schedule_result_t&lt;<em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><em><code class="sourceCode default">decay-copyable-result-datums</code></em>(cs); // see [exec.snd.expos]</span></code></pre></div>
</blockquote>

</div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
Objects of the local class
<em><code class="sourceCode default">state-type</code></em> <span style="color:blue;font-style=italic">… as before …</span></p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
Let <code class="sourceCode default">Sigs</code> be a pack of the
arguments to the
<code class="sourceCode default">completion_signatures</code>
specialization named by <code class="sourceCode default">completion_signatures_of_t&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">FWD-ENV-T</code></span></em>(</ins></span>env_of_t&lt;Rcvr&gt;<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span>&gt;</code>. Let
<em><code class="sourceCode default">as-tuple</code></em> be an alias
template such that <code class="sourceCode default"><em><code class="sourceCode default">as-tuple</code></em>&lt;Tag(Args...)&gt;</code>
denotes the type <code class="sourceCode default"><em><code class="sourceCode default">decayed-tuple</code></em>&lt;Tag, Args...&gt;</code>.
Then <code class="sourceCode default">variant_t</code> denotes the type
<code class="sourceCode default">variant&lt;monostate, <em><code class="sourceCode default">as-tuple</code></em>&lt;Sigs&gt;...&gt;</code>,
except with duplicate types removed.</p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.on] para 6 as follows
(<em><code class="sourceCode default">not-a-sender</code></em> is moved
to [exec.snd.expos]): ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
Otherwise: Let
<em><code class="sourceCode default">not-a-scheduler</code></em> be an
unspecified empty class type<span class="add" style="color: #006e28"><ins>.</ins></span><span class="rm" style="color: #bf0303"><del>, and let
<em><span><code class="sourceCode default">not-a-sender</code></span></em>
be the exposition-only type:</del></span></p>
<div class="rm" style="color: #bf0303">

<blockquote>
<div class="sourceCode" id="cb42"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a>struct <em><code class="sourceCode default">not-a-sender</code></em> {</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>  using sender_concept = sender_t;</span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>  auto get_completion_signatures(auto&amp;&amp;) const {</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>    return <em>see below</em>;</span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</blockquote>

</div>
<p><span class="rm" style="color: #bf0303"><del>where the member
function
<span><code class="sourceCode default">get_completion_signatures</code></span>
returns an object of a type that is not a specialization of the
<span><code class="sourceCode default">completion_signatures</code></span>
class template.</del></span></p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Delete
[exec.on] para 9 as follows: ]</span></p>
<div class="rm" style="color: #bf0303">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<span class="rm" style="color: #bf0303"><del><em>Recommended
practice</em>: Implementations should use the return type of <span><code class="sourceCode default"><em><code class="sourceCode default">not-a-sender</code></em>::get_completion_signatures</code></span>
to inform users that their usage of on is incorrect because there is no
available scheduler onto which to restore execution.</del></span></p>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.then] para 4 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<em><code class="sourceCode default">then-cpo</code></em> as
follows:</p>
<blockquote>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span><em><code class="sourceCode default">decayed-typeof</code></em><span class="op">&lt;</span><em><code class="sourceCode default">then-cpo</code></em><span class="op">&gt;&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> complete <span class="op">=</span></span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a>      <span class="op">[]&lt;</span><span class="kw">class</span> Tag, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb43-6"><a href="#cb43-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">(</span><span class="kw">auto</span>, <span class="kw">auto</span><span class="op">&amp;</span> fn, <span class="kw">auto</span><span class="op">&amp;</span> rcvr, Tag, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>          <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>same_as<span class="op">&lt;</span>Tag, <em><code class="sourceCode default">decayed-typeof</code></em><span class="op">&lt;</span><em><code class="sourceCode default">set-cpo</code></em><span class="op">&gt;&gt;)</span> <span class="op">{</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>            <em><code class="sourceCode default">TRY-SET-VALUE</code></em><span class="op">(</span>rcvr,</span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>                          invoke<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>fn<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...))</span>;</span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>            Tag<span class="op">()(</span>std<span class="op">::</span>move<span class="op">(</span>rcvr<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span>;</span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span></span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>;</span>
<span id="cb43-14"><a href="#cb43-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-15"><a href="#cb43-15" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb43-16"><a href="#cb43-16" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb43-17"><a href="#cb43-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb43-18"><a href="#cb43-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb44"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class... Env&gt;</span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>static consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
</div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<em>Effects:</em> Equivalent to:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a>auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>auto fn = []&lt;class... Ts&gt;(set_value_t(*)(Ts...)) {</span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a>  if constexpr (!invocable&lt;remove_cvref_t&lt;<em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;&gt;, Ts...&gt;)</span>
<span id="cb45-4"><a href="#cb45-4" aria-hidden="true" tabindex="-1"></a>    throw <em><code class="sourceCode default">unspecified</code></em>;</span>
<span id="cb45-5"><a href="#cb45-5" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb45-6"><a href="#cb45-6" aria-hidden="true" tabindex="-1"></a>cs.<em><code class="sourceCode default">for-each</code></em>(<em><code class="sourceCode default">overload-set</code></em>{fn, [](auto){}});</span></code></pre></div></li>
</ul>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.let] paras 5 and 6 and insert a new para after 6 as follows:
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<em><code class="sourceCode default">let-cpo</code></em> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> State, <span class="kw">class</span> Rcvr, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <em><code class="sourceCode default">let-bind</code></em><span class="op">(</span>State<span class="op">&amp;</span> state, Rcvr<span class="op">&amp;</span> rcvr, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span>;      <span class="co">// exposition only</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span><em><code class="sourceCode default">decayed-typeof</code></em><span class="op">&lt;</span><em><code class="sourceCode default">let-cpo</code></em><span class="op">&gt;&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-state</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb46-13"><a href="#cb46-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
Let <em><code class="sourceCode default">receiver2</code></em> denote
the following exposition-only class template:</p>
<blockquote>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style=italic">… as before …</span></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Invocation of the function
<code class="sourceCode default"><em><code class="sourceCode default">receiver2</code></em>::get_env</code>
returns an object <code class="sourceCode default">e</code> such
that</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span>
<code class="sourceCode default">decltype(e)</code> models
<em><code class="sourceCode default">queryable</code></em> and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span>
given a query object <code class="sourceCode default">q</code>, the
expression <code class="sourceCode default">e.query(q)</code> is
expression-equivalent to
<code class="sourceCode default"><em><code class="sourceCode default">env</code></em>.query(q)</code>
if that expression is valid<span class="rm" style="color: #bf0303"><del>,</del></span><span class="add" style="color: #006e28"><ins>;</ins></span> otherwise<span class="add" style="color: #006e28"><ins>, if the type of
<span><code class="sourceCode default">q</code></span> satisfies
<em><span><code class="sourceCode default">forwarding-query</code></span></em>,</ins></span>
<code class="sourceCode default">e.query(q)</code> is
expression-equivalent to
<code class="sourceCode default">get_env(<em><code class="sourceCode default">rcvr</code></em>).query(q)</code><span class="add" style="color: #006e28"><ins>; otherwise,
<span><code class="sourceCode default">e.query(q)</code></span> is
ill-formed</ins></span>.</p></li>
</ul>
<div class="add" style="color: #006e28">

<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb48"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class... Env&gt;</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
</div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<em>Effects:</em> Equivalent to:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>using LetFn = remove_cvref_t&lt;<em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;&gt;;</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>auto fn = []&lt;class... Ts&gt;(<em><code class="sourceCode default">decayed-typeof</code></em>&lt;<em><code class="sourceCode default">set-cpo</code></em>&gt;(*)(Ts...)) {</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>  if constexpr (!<em><code class="sourceCode default">is-valid-let-sender</code></em>)</span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>    throw <em><code class="sourceCode default">unspecified</code></em>;</span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>cs.<em><code class="sourceCode default">for-each</code></em>(<em><code class="sourceCode default">overload-set</code></em>(fn, [](auto){}));</span></code></pre></div>
<p>where
<em><code class="sourceCode default">is-valid-let-sender</code></em> is
<code class="sourceCode default">true</code> if and only if all of the
following are <code class="sourceCode default">true</code>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(?.1.1)</a></span>
<code class="sourceCode default">(constructible_from&lt;decay_t&lt;Ts&gt;, Ts&gt; &amp;&amp;...)</code></li>
<li><span class="marginalizedparent"><a class="marginalized">(?.1.2)</a></span>
<code class="sourceCode default">invocable&lt;LetFn, decay_t&lt;Ts&gt;&amp;...&gt;</code></li>
<li><span class="marginalizedparent"><a class="marginalized">(?.1.3)</a></span>
<code class="sourceCode default">sender&lt;invoke_result_t&lt;LetFn, decay_t&lt;Ts&gt;&amp;...&gt;&gt;</code></li>
<li><span class="marginalizedparent"><a class="marginalized">(?.1.4)</a></span>
<code class="sourceCode default">sizeof...(Env) == 0 || sender_in&lt;invoke_result_t&lt;LetFn, decay_t&lt;Ts&gt;&amp;...&gt;, <em><code class="sourceCode default">env-t</code></em>...&gt;</code></li>
</ul>
<p>where <em><code class="sourceCode default">env-t</code></em> is the
pack <code class="sourceCode default">decltype(<em><code class="sourceCode default">let-cpo</code></em>.transform_env(declval&lt;Sndr&gt;(), declval&lt;Env&gt;()))</code>.</p></li>
</ul>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
following changes are the proposed resolutions to <a href="https://github.com/cplusplus/sender-receiver/issues/316">cplusplus/sender-receiver#316</a>
and <a href="https://github.com/cplusplus/sender-receiver/issues/318">cplusplus/sender-receiver#318</a>.
]</span></p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;<em><code class="sourceCode default">decayed-typeof</code></em>&lt;<em><code class="sourceCode default">let-cpo</code></em>&gt;&gt;::<em><code class="sourceCode default">get-state</code></em></code>
is initialized with a callable object equivalent to the following:</p>
<blockquote>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="op">[]&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Rcvr<span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">requires</span> <em><code class="sourceCode default">see below</code></em> <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">&amp;</span> <span class="op">[</span>_, fn, child<span class="op">]</span> <span class="op">=</span> sndr;</span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> fn_t <span class="op">=</span> decay_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>fn<span class="op">)&gt;</span>;</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> env_t <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span><em><code class="sourceCode default">let-env</code></em><span class="op">(</span>child<span class="op">))</span>;</span>
<span id="cb50-5"><a href="#cb50-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> args_variant_t <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb50-6"><a href="#cb50-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> ops2_variant_t <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb50-7"><a href="#cb50-7" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;font-style=italic">… as before …</span></span>
<span id="cb50-8"><a href="#cb50-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
Let <code class="sourceCode default">Sigs</code> be a pack of the
arguments to the
<code class="sourceCode default">completion_signatures</code>
specialization named by <code class="sourceCode default">completion_signatures_of_t&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">FWD-ENV-T</code></span></em>(</ins></span>env_of_t&lt;Rcvr&gt;<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span>&gt;</code>. Let
<code class="sourceCode default">LetSigs</code> be a pack of those types
in <code class="sourceCode default">Sigs</code> with a return type of
<code class="sourceCode default"><em><code class="sourceCode default">decayed-typeof</code></em>&lt;<em><code class="sourceCode default">set-cpo</code></em>&gt;</code>.
Let <em><code class="sourceCode default">as-tuple</code></em> be an
alias template such that <code class="sourceCode default"><em><code class="sourceCode default">as-tuple</code></em>&lt;Tag(Args...)&gt;</code>
denotes the type <code class="sourceCode default"><em><code class="sourceCode default">decayed-tuple</code></em>&lt;Args...&gt;</code>.
Then <code class="sourceCode default">args_variant_t</code> denotes the
type <code class="sourceCode default">variant&lt;monostate, <em><code class="sourceCode default">as-tuple</code></em>&lt;LetSigs&gt;...&gt;</code>
except with duplicate types removed.</p>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
Given a type <code class="sourceCode default">Tag</code> and a pack
<code class="sourceCode default">Args</code>, let
<em><code class="sourceCode default">as-sndr2</code></em> be an alias
template such that <code class="sourceCode default"><em><code class="sourceCode default">as-sndr2</code></em>&lt;Tag(Args...)&gt;</code>
denotes the type <code class="sourceCode default"><em><code class="sourceCode default">call-result-t</code></em>&lt;Fn, decay_t&lt;Args&gt;&amp;...&gt;</code>.
Then <code class="sourceCode default">ops2_variant_t</code> denotes the
type</p>
<blockquote>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>variant<span class="op">&lt;</span>monostate, connect_result_t<span class="op">&lt;</span><em><code class="sourceCode default">as-sndr2</code></em><span class="op">&lt;</span>LetSigs<span class="op">&gt;</span>, receiver2<span class="op">&lt;</span>Rcvr, <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">Env</code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">env_t</code></span></ins></span><span class="op">&gt;&gt;...&gt;</span></span></code></pre></div>
</blockquote>
<p>except with duplicate types removed.</p>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span> The
<em><code class="sourceCode default">requires-clause</code></em>
constraining the above lambda is satisfied if and only if the types
<code class="sourceCode default">args_variant_t</code> and
<code class="sourceCode default">ops2_variant_t</code> are
well-formed.</p>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span> The
exposition-only function template
<em><code class="sourceCode default">let-bind</code></em> has effects
equivalent to: <span style="color:blue;font-style=italic">… as before
…</span></p>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span> <span style="color:blue;font-style=italic">… as before …</span></p>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
following change to [exec.let] para 13 is the proposed resolution to <a href="https://github.com/cplusplus/sender-receiver/issues/319">cplusplus/sender-receiver#319</a>.
]</span></p>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span> Let
<code class="sourceCode default">sndr</code> and
<code class="sourceCode default">env</code> be subexpressions, and let
<code class="sourceCode default">Sndr</code> be
<code class="sourceCode default">decltype((sndr))</code>. If <code class="sourceCode default"><em><code class="sourceCode default">sender-for</code></em>&lt;Sndr, <em><code class="sourceCode default">decayed-typeof</code></em>&lt;<em><code class="sourceCode default">let-cpo</code></em>&gt;&gt;</code>
is <code class="sourceCode default">false</code>, then the expression
<code class="sourceCode default"><em><code class="sourceCode default">let-cpo</code></em>.transform_env(sndr, env)</code>
is ill-formed. Otherwise, it is equal to <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">JOIN-ENV</code></em>(<em><code class="sourceCode default">let-env</code></em>(sndr), <em><code class="sourceCode default">FWD-ENV</code></em>(env))</code></span>.</del></span></p>
<blockquote>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">auto&amp; [_, _, child] = sndr;</code></span></ins></span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">return <em><code class="sourceCode default">JOIN-ENV</code></em>(<em><code class="sourceCode default">let-env</code></em>(child), <em><code class="sourceCode default">FWD-ENV</code></em>(env));</code></span></ins></span></span></code></pre></div>
</blockquote>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.bulk] para 3 and insert a new para after 5 as follows:
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<code class="sourceCode default">bulk_t</code> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span>bulk_t<span class="op">&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;bulk_t&gt;::<em><code class="sourceCode default">complete</code></em></code>
is <span style="color:blue;font-style=italic">… as before …</span></p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<span style="color:blue;font-style=italic">… as before …</span></p>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb54"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class... Env&gt;</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
</div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<em>Effects:</em> Equivalent to:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a>auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>auto fn = []&lt;class... Ts&gt;(set_value_t(*)(Ts...)) {</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>  if constexpr (!invocable&lt;remove_cvref_t&lt;<em><code class="sourceCode default">data-type</code></em>&lt;Sndr&gt;&gt;, Ts&amp;...&gt;)</span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a>    throw <em><code class="sourceCode default">unspecified</code></em>;</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a>cs.<em><code class="sourceCode default">for-each</code></em>(<em><code class="sourceCode default">overload-set</code></em>{fn, [](auto){}});</span></code></pre></div></li>
</ul>
</blockquote>

</div>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
Let the subexpression <code class="sourceCode default">out_sndr</code>
denote <span style="color:blue;font-style=italic">… as before
…</span></p>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.split] para 3 and insert a new para after 3 as follows:
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The name <code class="sourceCode default">split</code> denotes a
pipeable sender adaptor object. <span class="rm" style="color: #bf0303"><del>For a subexpression
<span><code class="sourceCode default">sndr</code></span>, let
<span><code class="sourceCode default">Sndr</code></span> be
<span><code class="sourceCode default">decltype((sndr))</code></span>.
If <span><code class="sourceCode default">sender_in&lt;Sndr, <em><code class="sourceCode default">split-env</code></em>&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>,
<span><code class="sourceCode default">split(sndr)</code></span> is
ill-formed.</del></span></p>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<code class="sourceCode default">split_t</code> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb56"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>namespace std::execution {</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>  template&lt;&gt;</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a>  struct <em><code class="sourceCode default">impls-for</code></em>&lt;split_t&gt; : <em><code class="sourceCode default">default-impls</code></em> {</span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>    template&lt;class Sndr&gt;</span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>    static consteval void <em><code class="sourceCode default">check-types</code></em>() {</span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a>      auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">split-env</code></em>&gt;();</span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>      <em><code class="sourceCode default">decay-copyable-result-datums</code></em>(cs); // see [exec.snd.expos]</span>
<span id="cb56-8"><a href="#cb56-8" aria-hidden="true" tabindex="-1"></a>    }</span>
<span id="cb56-9"><a href="#cb56-9" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb56-10"><a href="#cb56-10" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</blockquote>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.when.all] paras 2-9 and insert two new paras after 4 as follows:
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The names <code class="sourceCode default">when_all</code> and
<code class="sourceCode default">when_all_with_variant</code> denote
customization point objects. Let
<code class="sourceCode default">sndrs</code> be a pack of
subexpressions, let <code class="sourceCode default">Sndrs</code> be a
pack of the types
<code class="sourceCode default">decltype((sndrs))...</code>, and let
<code class="sourceCode default">CD</code> be the type <code class="sourceCode default">common_type_t&lt;decltype(<em><code class="sourceCode default">get-domain-early</code></em>(sndrs))...&gt;</code>
<span class="add" style="color: #006e28"><ins>, and let
<span><code class="sourceCode default">CD2</code></span> be
<span><code class="sourceCode default">CD</code></span> if
<span><code class="sourceCode default">CD</code></span> is well-formed,
and <span><code class="sourceCode default">default_domain</code></span>
otherwise</ins></span>. The expressions
<code class="sourceCode default">when_all(sndrs...)</code> and
<code class="sourceCode default">when_all_with_variant(sndrs...)</code>
are ill-formed if any of the following is true:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
<code class="sourceCode default">sizeof...(sndrs)</code> is
<code class="sourceCode default">0</code>, or</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
<code class="sourceCode default">(sender&lt;Sndrs&gt; &amp;&amp; ...)</code>
is <code class="sourceCode default">false</code><span class="rm" style="color: #bf0303"><del>, or</del></span><span class="add" style="color: #006e28"><ins>.</ins></span></p></li>
</ul>
<div class="rm" style="color: #bf0303">

<ul>
<li><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">CD</code></span>
is ill-formed.</del></span></li>
</ul>

</div>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The expression
<code class="sourceCode default">when_all(sndrs...)</code> is
expression-equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a>transform_sender<span class="op">(</span><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">CD()</code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">CD2()</code></span></ins></span>, <em><code class="sourceCode default">make-sender</code></em><span class="op">(</span>when_all, <span class="op">{}</span>, sndrs<span class="op">...))</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<code class="sourceCode default">when_all_t</code> as follows:</p>
<blockquote>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span>when_all_t<span class="op">&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-attrs</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-env</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-state</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">start</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>();</code></span></ins></span></span>
<span id="cb58-12"><a href="#cb58-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb58-13"><a href="#cb58-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<span class="add" style="color: #006e28"><ins>Let
<span><code class="sourceCode default">make-when-all-env</code></span>
be the following exposition-only function template:</ins></span></p>
<blockquote>
<div class="sourceCode" id="cb59"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Env&gt;</span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>constexpr auto <em><code class="sourceCode default">make-when-all-env</code></em>(inplace_stop_source&amp; stop_src, Env&amp;&amp; env) noexcept {</span>
<span id="cb59-3"><a href="#cb59-3" aria-hidden="true" tabindex="-1"></a>  return <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb59-4"><a href="#cb59-4" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</blockquote>

</div>
<p>Returns an object <code class="sourceCode default">e</code> such that
<span class="ednote" style="color: #0000ff">[ Editor&#39;s note: The
following itemized list has been moved here from para 6 and modified as
indicated. ]</span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<code class="sourceCode default">decltype(e)</code> models
<code class="sourceCode default">queryable</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.2)</a></span>
<code class="sourceCode default">e.query(get_stop_token)</code> is
expression-equivalent to
<code class="sourceCode default">stop_src.get_token()</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.3)</a></span>
given a query object <code class="sourceCode default">q</code> with type
other than <em>cv</em>
<code class="sourceCode default">stop_token_t</code> <span class="add" style="color: #006e28"><ins>and whose type satisfies
<em><span><code class="sourceCode default">forwarding-query</code></span></em></ins></span>,
<code class="sourceCode default">e.query(q)</code> is
expression-equivalent to
<code class="sourceCode default">env.query(q)</code>.</p></li>
</ul>
<p><span class="add" style="color: #006e28"><ins>Let
<em><span><code class="sourceCode default">when-all-env</code></span></em>
be an alias template such that
<span><code class="sourceCode default"><em><code class="sourceCode default">when-all-env</code></em>&lt;Env&gt;</code></span>
denotes the type <span><code class="sourceCode default">decltype(<em><code class="sourceCode default">make-when-all-env</code></em>(declval&lt;inplace_stop_source&amp;&gt;(), declval&lt;Env&gt;()))</code></span>.</ins></span></p>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<span class="marginalizedparent"><a class="marginalized">?</a></span>
<div>
<div class="sourceCode" id="cb60"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a>template&lt;class Sndr, class... Env&gt;</span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>consteval void <em><code class="sourceCode default">check-types</code></em>();</span></code></pre></div>
</div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.1)</a></span>
<span class="add" style="color: #006e28"><ins>Let
<span><code class="sourceCode default">Is</code></span> be the pack of
integral template arguments of the
<span><code class="sourceCode default">integer_sequence</code></span>
specialization denoted by
<span><code class="sourceCode default"><em><code class="sourceCode default">indices-for</code></em>&lt;Sndr&gt;</code></span>.</ins></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.2)</a></span>
<span class="add" style="color: #006e28"><ins><em>Effects</em>:
Equivalent to:</ins></span></p>
<div class="sourceCode" id="cb61"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>auto fn = []&lt;class Child&gt;() {</span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>  auto cs = get_completion_signatures&lt;Child, <em><code class="sourceCode default">when-all-env</code></em>&lt;Env&gt;...&gt;();</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>  if constexpr (cs.<em><code class="sourceCode default">count-of</code></em>(set_value) &gt;= 2)</span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a>    throw <em><code class="sourceCode default">unspecified</code></em>;</span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a>  <em><code class="sourceCode default">decay-copyable-result-datums</code></em>(cs); // see [exec.snd.expos]</span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>(fn.template operator()&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr, Is&gt;&gt;(), ...);</span></code></pre></div></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(?.3)</a></span>
<span class="add" style="color: #006e28"><ins><em>Throws</em>: Any
exception thrown as a result of evaluating the <em>Effects</em>, or an
exception of an unspecified type derived from
<span><code class="sourceCode default">exception</code></span> when
<span><code class="sourceCode default">CD</code></span> is
ill-formed.</ins></span></p></li>
</ul>
</blockquote>

</div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;when_all_t&gt;::<em><code class="sourceCode default">get-attrs</code></em></code>
<span style="color:blue;text-style:italic">… as before …</span></p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;when_all_t&gt;::<em><code class="sourceCode default">get-env</code></em></code>
is initialized with a callable object equivalent to the following lambda
expression:</p>
<blockquote>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="op">[]&lt;</span><span class="kw">class</span> State, <span class="kw">class</span> Rcvr<span class="op">&gt;(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span>, State<span class="op">&amp;</span> state, <span class="kw">const</span> Receiver<span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">see below</code></em></code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">make-when-all-env</code></em>(state.<em><code class="sourceCode default">stop-src</code></em>, get_env(rcvr))</code></span></ins></span>;</span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<div class="rm" style="color: #bf0303">

<blockquote>
<p><span class="rm" style="color: #bf0303"><del>Returns an object
<span><code class="sourceCode default">e</code></span> such
that</del></span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">decltype(e)</code></span>
models <span><code class="sourceCode default">queryable</code></span>,
and</del></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span>
<span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">e.query(get_stop_token)</code></span>
is expression-equivalent to
<span><code class="sourceCode default">state.<em><code class="sourceCode default">stop-src</code></em>.get_token()</code></span>,
and</del></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.3)</a></span>
<span class="rm" style="color: #bf0303"><del>given a query object
<span><code class="sourceCode default">q</code></span> with type other
than <em>cv</em>
<span><code class="sourceCode default">stop_token_t</code></span>,
<span><code class="sourceCode default">e.query(q)</code></span> is
expression-equivalent to
<span><code class="sourceCode default">get_env(rcvr).query(q)</code></span>.</del></span></p></li>
</ul>
</blockquote>

</div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;when_all_t&gt;::<em><code class="sourceCode default">get-state</code></em></code>
is initialized with a callable object equivalent to the following lambda
expression:</p>
<blockquote>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="op">[]&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Rcvr<span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em>e</em><span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><em>e</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <em>e</em>;</span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>where <em><code class="sourceCode default">e</code></em> is the
expression</p>
<blockquote>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>forward<span class="op">&lt;</span>Sndr<span class="op">&gt;(</span>sndr<span class="op">).</span>apply<span class="op">(</span><em><code class="sourceCode default">make-state</code></em><span class="op">&lt;</span>Rcvr<span class="op">&gt;())</span></span></code></pre></div>
</blockquote>
<p>and where <em><code class="sourceCode default">make-state</code></em>
is the following exposition-only class template:</p>
<blockquote>
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">template&lt;class Sndr, class Env&gt;</code></span></del></span></span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">concept <em><code class="sourceCode default">max-1-sender-in</code></em> = sender_in&lt;Sndr, Env&gt; &amp;&amp;</code></span></del></span>                <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">// exposition only</code></span></del></span><span class="op">@</span></span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a>  <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">(tuple_size_v&lt;value_types_of_t&lt;Sndr, Env, tuple, tuple&gt;&gt; &lt;= 1);</code></span></del></span></span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> disposition <span class="op">{</span> started, error, stopped <span class="op">}</span>;             <span class="co">// exposition only</span></span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb65-7"><a href="#cb65-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Rcvr<span class="op">&gt;</span></span>
<span id="cb65-8"><a href="#cb65-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> make<span class="op">-</span>state <span class="op">{</span></span>
<span id="cb65-9"><a href="#cb65-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default"><em><code class="sourceCode default">max-1-sender-in</code></em>&lt;env_of_t&lt;Rcvr&gt;&gt;</code></span></del></span><span class="add" style="color: #006e28"><ins>class</ins></span><span class="op">...</span> Sndrs<span class="op">&gt;</span></span>
<span id="cb65-10"><a href="#cb65-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">auto</span>, <span class="kw">auto</span>, Sndrs<span class="op">&amp;&amp;...</span> sndrs<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb65-11"><a href="#cb65-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> values_tuple <span class="op">=</span> see below;</span>
<span id="cb65-12"><a href="#cb65-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> errors_variant <span class="op">=</span> see below;</span>
<span id="cb65-13"><a href="#cb65-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> stop_callback <span class="op">=</span> stop_callback_for_t<span class="op">&lt;</span>stop_token_of_t<span class="op">&lt;</span>env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;&gt;</span>, on<span class="op">-</span>stop<span class="op">-</span>request<span class="op">&gt;</span>;</span>
<span id="cb65-14"><a href="#cb65-14" aria-hidden="true" tabindex="-1"></a><span style="color:blue;font-style:italic">… as before …</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
Let <em><code class="sourceCode default">copy-fail</code></em> be <span style="color:blue;font-style:italic">… as before …</span></p>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
The alias <code class="sourceCode default">values_tuple</code> denotes
the type</p>
<blockquote>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a>tuple<span class="op">&lt;</span>value_types_of_t<span class="op">&lt;</span>Sndrs, <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV-T</code></em>(</code></span></ins></span>env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;</span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span>, decayed<span class="op">-</span>tuple, optional<span class="op">&gt;...&gt;</span></span></code></pre></div>
</blockquote>
<p>if that type is well-formed; otherwise,
<code class="sourceCode default">tuple&lt;&gt;</code>.</p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.when.all] para 14 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span> The
expression
<code class="sourceCode default">when_all_with_variant(sndrs...)</code>
is expression-equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a>transform_sender<span class="op">(</span><span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">CD()</code></span></del></span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">CD2()</code></span></ins></span>, <em><code class="sourceCode default">make-sender</code></em><span class="op">(</span>when_all_with_variant, <span class="op">{}</span>, sndrs<span class="op">...))</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.into.variant] paras 4-5 as follows (with the change to para 5
being a drive-by fix): ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The exposition-only class template
<em><code class="sourceCode default">impls-for</code></em>
([exec.snd.general]) is specialized for
<em><code class="sourceCode default">into_variant</code></em> as
follows:</p>
<blockquote>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;&gt;</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em><code class="sourceCode default">impls-for</code></em><span class="op">&lt;</span>into_variant_t<span class="op">&gt;</span> <span class="op">:</span> <em><code class="sourceCode default">default-impls</code></em> <span class="op">{</span></span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">get-state</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb68-5"><a href="#cb68-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <em><code class="sourceCode default">complete</code></em> <span class="op">=</span> <em><code class="sourceCode default">see below</code></em>;</span>
<span id="cb68-6"><a href="#cb68-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Sndr, class... Env&gt;</code></span></ins></span></span>
<span id="cb68-8"><a href="#cb68-8" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static consteval void <em><code class="sourceCode default">check-types</code></em>() {</code></span></ins></span></span>
<span id="cb68-9"><a href="#cb68-9" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">auto cs = get_completion_signatures&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;();</code></span></ins></span></span>
<span id="cb68-10"><a href="#cb68-10" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">decay-copyable-result-datums</code></em>(cs);</code></span></ins></span>  <span class="co">// see [exec.snd.expos]</span></span>
<span id="cb68-11"><a href="#cb68-11" aria-hidden="true" tabindex="-1"></a>    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">}</code></span></ins></span></span>
<span id="cb68-12"><a href="#cb68-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb68-13"><a href="#cb68-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
The member <code class="sourceCode default"><em><code class="sourceCode default">impls-for</code></em>&lt;into_variant_t&gt;::<em><code class="sourceCode default">get-state</code></em></code>
is initialized with a callable object equivalent to the following
lambda:</p>
<blockquote>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a><span class="op">[]&lt;</span><span class="kw">class</span> Sndr, <span class="kw">class</span> Rcvr<span class="op">&gt;(</span>Sndr<span class="op">&amp;&amp;</span> sndr, Rcvr<span class="op">&amp;</span> rcvr<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> type_identity<span class="op">&lt;</span>value_types_of_t<span class="op">&lt;</span><em><code class="sourceCode default">child-type</code></em><span class="op">&lt;</span>Sndr<span class="op">&gt;</span>, <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV-T</code></em>(</code></span></ins></span>env_of_t<span class="op">&lt;</span>Rcvr<span class="op">&gt;</span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span><span class="op">&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.stopped.opt] as follows. Note: this includes the proposed
resolution to <a href="https://github.com/cplusplus/sender-receiver/issues/311">cplusplus/sender-receiver#311</a>
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The name <code class="sourceCode default">stopped_as_optional</code>
denotes a pipeable sender adaptor object. For a subexpression
<code class="sourceCode default">sndr</code>, let
<code class="sourceCode default">Sndr</code> be
<code class="sourceCode default">decltype((sndr))</code>. The expression
<code class="sourceCode default">stopped_as_optional(sndr)</code> is
expression-equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a>transform_sender<span class="op">(</span><em><code class="sourceCode default">get-domain-early</code></em><span class="op">(</span>sndr<span class="op">)</span>, <em><code class="sourceCode default">make-sender</code></em><span class="op">(</span>stopped_as_optional, <span class="op">{}</span>, sndr<span class="op">))</span></span></code></pre></div>
</blockquote>
<p>except that <code class="sourceCode default">sndr</code> is only
evaluated once.</p>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<span class="add" style="color: #006e28"><ins>The exposition-only class
template
<em><span><code class="sourceCode default">impls-for</code></span></em>
([exec.snd.general]) is specialized for
<span><code class="sourceCode default">stopped_as_optional_t</code></span>
as follows:</ins></span></p>
<blockquote>
<div class="sourceCode" id="cb71"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a>template&lt;&gt;</span>
<span id="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a>struct <em><code class="sourceCode default">impls-for</code></em>&lt;stopped_as_optional_t&gt; : <em><code class="sourceCode default">default-impls</code></em> {</span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a>  template&lt;class Sndr, class... Env&gt;</span>
<span id="cb71-4"><a href="#cb71-4" aria-hidden="true" tabindex="-1"></a>  static consteval void <em><code class="sourceCode default">check-types</code></em>() {</span>
<span id="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a>    <em><code class="sourceCode default">default-impls</code></em>::<em><code class="sourceCode default">check-types</code></em>&lt;Sndr, Env...&gt;();</span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>    if constexpr (!requires {</span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a>      requires (!same_as&lt;void, <em><code class="sourceCode default">single-sender-value-type</code></em>&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)...&gt;&gt;); })</span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a>      throw <em>unspecified</em>;</span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</blockquote>

</div>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
Let <code class="sourceCode default">sndr</code> and
<code class="sourceCode default">env</code> be subexpressions such that
<code class="sourceCode default">Sndr</code> is
<code class="sourceCode default">decltype((sndr))</code> and
<code class="sourceCode default">Env</code> is
<code class="sourceCode default">decltype((env))</code>. If <code class="sourceCode default"><em><code class="sourceCode default">sender-for</code></em>&lt;Sndr, stopped_as_optional_t&gt;</code>
is <code class="sourceCode default">false</code><span class="rm" style="color: #bf0303"><del>, or if the type <span><code class="sourceCode default"><em><code class="sourceCode default">single-sender-value-type</code></em>&lt;Sndr, Env&gt;</code></span>
is ill-formed or
<span><code class="sourceCode default">void</code></span>,</del></span>
then the expression <code class="sourceCode default">stopped_as_optional.transform_sender(sndr, env)</code>
is ill-formed; <span class="add" style="color: #006e28"><ins>otherwise,
if <span><code class="sourceCode default">sender_in&lt;<em><code class="sourceCode default">child-type</code></em>&lt;Sndr&gt;, <em><code class="sourceCode default">FWD-ENV-T</code></em>(Env)&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>, the
expression <span><code class="sourceCode default">stopped_as_optional.transform_sender(sndr, env)</code></span>
is equivalent to
<span><code class="sourceCode default"><em><code class="sourceCode default">not-a-sender</code></em>()</code></span>;</ins></span>
otherwise, it is equivalent to:</p>
<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span><span class="op">&amp;&amp;</span> <span class="op">[</span>_, _, child<span class="op">]</span> <span class="op">=</span> sndr;</span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> V <span class="op">=</span> <em><code class="sourceCode default">single-sender-value-type</code></em><span class="op">&lt;</span><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">child-type</code></em>&lt;</code></span></ins></span>Sndr<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&gt;</code></span></ins></span>, <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em><code class="sourceCode default">FWD-ENV-T</code></em>(</code></span></ins></span>Env<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">)</code></span></ins></span><span class="op">&gt;</span>;</span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> let_stopped<span class="op">(</span></span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a>    then<span class="op">(</span>std<span class="op">::</span>forward_like<span class="op">&lt;</span>Sndr<span class="op">&gt;(</span>child<span class="op">)</span>,</span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>         <span class="op">[]&lt;</span><span class="kw">class</span><span class="op">...</span> Ts<span class="op">&gt;(</span>Ts<span class="op">&amp;&amp;...</span> ts<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span>is_nothrow_constructible_v<span class="op">&lt;</span>V, Ts<span class="op">...&gt;)</span> <span class="op">{</span></span>
<span id="cb72-6"><a href="#cb72-6" aria-hidden="true" tabindex="-1"></a>           <span class="cf">return</span> optional<span class="op">&lt;</span>V<span class="op">&gt;(</span>in_place, std<span class="op">::</span>forward<span class="op">&lt;</span>Ts<span class="op">&gt;(</span>ts<span class="op">)...)</span>;</span>
<span id="cb72-7"><a href="#cb72-7" aria-hidden="true" tabindex="-1"></a>         <span class="op">})</span>,</span>
<span id="cb72-8"><a href="#cb72-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">[]()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> just<span class="op">(</span>optional<span class="op">&lt;</span>V<span class="op">&gt;())</span>; <span class="op">})</span>;</span></code></pre></div>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.sync.wait] as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The name <code class="sourceCode default">this_thread::sync_wait</code>
denotes a customization point object. For a subexpression
<code class="sourceCode default">sndr</code>, let
<code class="sourceCode default">Sndr</code> be
<code class="sourceCode default">decltype((sndr))</code>. <span class="rm" style="color: #bf0303"><del>If <span><code class="sourceCode default">sender_in&lt;Sndr, <em><code class="sourceCode default">sync-wait-env</code></em>&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>, the
expression
<span><code class="sourceCode default">this_thread::sync_wait(sndr)</code></span>
is ill-formed. Otherwise, it</del></span> <span class="add" style="color: #006e28"><ins>The expression
<span><code class="sourceCode default">this_thread::sync_wait(sndr)</code></span></ins></span>
is expression-equivalent to the following, except that
<code class="sourceCode default">sndr</code> is evaluated only once:</p>
<blockquote>
<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>apply_sender<span class="op">(</span><em><code class="sourceCode default">get-domain-early</code></em><span class="op">(</span>sndr<span class="op">)</span>, sync_wait, sndr<span class="op">)</span></span></code></pre></div>
</blockquote>
<p><em>Mandates</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.?)</a></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">sender_in&lt;Sndr, <em><code class="sourceCode default">sync-wait-env</code></em>&gt;</code></span>
is
<span><code class="sourceCode default">true</code></span>.</ins></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.1)</a></span> The
type <code class="sourceCode default"><em><code class="sourceCode default">sync-wait-result-type</code></em>&lt;Sndr&gt;</code>
is well-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.2)</a></span>
<code class="sourceCode default">same_as&lt;decltype(<em><code class="sourceCode default">e</code></em>), <em><code class="sourceCode default">sync-wait-result-type</code></em>&lt;Sndr&gt;&gt;</code>
is <code class="sourceCode default">true</code>, where
<em><code class="sourceCode default">e</code></em> is the
<code class="sourceCode default">apply_sender</code> expression
above.</p>
</li>
<p><span style="color:blue"><em>…as before</em></span></p></li>
</ul>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.sync.wait.var] as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The name <code class="sourceCode default">this_thread::sync_wait_with_variant</code>
denotes a customization point object. For a subexpression
<code class="sourceCode default">sndr</code>, let
<code class="sourceCode default">Sndr</code> be
<code class="sourceCode default">decltype(into_variant(sndr))</code>.
<span class="rm" style="color: #bf0303"><del>If <span><code class="sourceCode default">sender_in&lt;Sndr, <em><code class="sourceCode default">sync-wait-env</code></em>&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>, the
expression
<span><code class="sourceCode default">this_thread::sync_wait(sndr)</code></span>
is ill-formed. Otherwise, it</del></span> <span class="add" style="color: #006e28"><ins>The expression <span><code class="sourceCode default">this_thread::sync_wait_with_variant(sndr)</code></span></ins></span>
is expression-equivalent to the following, except that
<code class="sourceCode default">sndr</code> is evaluated only once:</p>
<blockquote>
<div class="sourceCode" id="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-1"></a>apply_sender<span class="op">(</span><em><code class="sourceCode default">get-domain-early</code></em><span class="op">(</span>sndr<span class="op">)</span>, sync_wait_with_variant, sndr<span class="op">)</span></span></code></pre></div>
</blockquote>
<p><em>Mandates</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.?)</a></span>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">sender_in&lt;Sndr, <em><code class="sourceCode default">sync-wait-env</code></em>&gt;</code></span>
is
<span><code class="sourceCode default">true</code></span>.</ins></span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span> The
type <code class="sourceCode default"><em><code class="sourceCode default">sync-wait-with-variant-result-type</code></em>&lt;Sndr&gt;</code>
is well-formed.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
<code class="sourceCode default">same_as&lt;decltype(<em><code class="sourceCode default">e</code></em>), <em><code class="sourceCode default">sync-wait-with-variant-result-type</code></em>&lt;Sndr&gt;&gt;</code>
is <code class="sourceCode default">true</code>, where
<em><code class="sourceCode default">e</code></em> is the
<code class="sourceCode default">apply_sender</code> expression
above.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<span class="rm" style="color: #bf0303"><del>If <span><code class="sourceCode default"><em><code class="sourceCode default">callable</code></em>&lt;sync_wait_t, Sndr&gt;</code></span>
is <span><code class="sourceCode default">false</code></span>, the
expression <span><code class="sourceCode default">sync_wait_with_variant.apply_sender(sndr)</code></span>
is ill-formed. Otherwise, it</del></span> <span class="add" style="color: #006e28"><ins>The expression <span><code class="sourceCode default">sync_wait_with_variant.apply_sender(sndr)</code></span></ins></span>
is equivalent to <span style="color:blue"><em>…as before</em></span></p>
</blockquote>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.util.cmplsig] para 8 and add a new para after 8 as follows:
]</span></p>
<blockquote>
<span class="marginalizedparent"><a class="marginalized">8</a></span>
<div>
<div class="sourceCode" id="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em><code class="sourceCode default">completion-signature</code></em><span class="op">...</span> Fns<span class="op">&gt;</span></span>
<span id="cb75-3"><a href="#cb75-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> completion_signatures <span class="op">{</span></span>
<span id="cb75-4"><a href="#cb75-4" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Tag&gt;</code></span></ins></span></span>
<span id="cb75-5"><a href="#cb75-5" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static constexpr size_t <em><code class="sourceCode default">count-of</code></em>(Tag) { return <em><code class="sourceCode default">see below</code></em>; }</code></span></ins></span></span>
<span id="cb75-6"><a href="#cb75-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-7"><a href="#cb75-7" aria-hidden="true" tabindex="-1"></a>      <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class Fn&gt;</code></span></ins></span></span>
<span id="cb75-8"><a href="#cb75-8" aria-hidden="true" tabindex="-1"></a>        <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">static constexpr void <em><code class="sourceCode default">for-each</code></em>(Fn&amp;&amp; fn) { // exposition only</code></span></ins></span></span>
<span id="cb75-9"><a href="#cb75-9" aria-hidden="true" tabindex="-1"></a>          <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">(std::forward&lt;Fn&gt;(fn)(static_cast&lt;Fns*&gt;(nullptr)), ...);</code></span></ins></span></span>
<span id="cb75-10"><a href="#cb75-10" aria-hidden="true" tabindex="-1"></a>        <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">}</code></span></ins></span></span>
<span id="cb75-11"><a href="#cb75-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb75-12"><a href="#cb75-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb75-13"><a href="#cb75-13" aria-hidden="true" tabindex="-1"></a>  <span style="color:blue;text-style:italic">… as before …</span></span>
<span id="cb75-14"><a href="#cb75-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</div>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">?</a></span>
<span class="add" style="color: #006e28"><ins>For a subexpression
<span><code class="sourceCode default">tag</code></span>, let
<span><code class="sourceCode default">Tag</code></span> be the decayed
type of <span><code class="sourceCode default">tag</code></span>.
<span><code class="sourceCode default">completion_signatures&lt;Fns...&gt;::<em><code class="sourceCode default">count-of</code></em>(tag)</code></span>
returns the count of function types in
<span><code class="sourceCode default">Fns...</code></span> that are of
the form <span><code class="sourceCode default">Tag(Ts...)</code></span>
where <span><code class="sourceCode default">Ts</code></span> is a pack
of types.</ins></span></p>
</blockquote>

</div>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Remove
subclause [exec.util.cmplsig.trans]. ]</span></p>
<p><span class="ednote" style="color: #0000ff">[ Editor&#39;s note: Change
[exec.run.loop.types] para 5 as follows: ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em><code class="sourceCode default">run-loop-sender</code></em> is an
exposition-only type that satisfies
<code class="sourceCode default">sender</code>. <span class="rm" style="color: #bf0303"><del>For any type
<span><code class="sourceCode default">Env</code></span>,</del></span>
<code class="sourceCode default">completion_signatures_of_t&lt;<em><code class="sourceCode default">run-loop-sender</code></em><span class="rm" style="color: #bf0303"><del>, Env</del></span>&gt;</code> is
<code class="sourceCode default">completion_signatures&lt;set_value_t(), set_error_t(exception_ptr), set_stopped_t()&gt;</code>.</p>
</blockquote>
<h1 data-number="8" id="acknowledgements"><span class="header-section-number">8</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>I would like to thank Hana Dusíková for her work making constexpr
exceptions a reality for C++26. Thanks are also due to David Sankel for
his encouragement to investigate using constexpr exceptions as an
alternative to TMP hackery, and for giving feedback on an early draft of
this paper.</p>
<h1 data-number="9" id="bibliography"><span class="header-section-number">9</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-P3068R6" class="csl-entry" role="doc-biblioentry">
[P3068R6] Hana Dusíková. 2024-11-19. Allowing exception throwing in
constant-evaluation. <a href="https://wg21.link/p3068r6"><div class="csl-block">https://wg21.link/p3068r6</div></a>
</div>
<div id="ref-P3164R4" class="csl-entry" role="doc-biblioentry">
[P3164R4] Eric Niebler. Early Diagnostics for Sender Expressions. <a href="https://isocpp.org/files/papers/P3164R4.html"><div class="csl-block">https://isocpp.org/files/papers/P3164R4.html</div></a>
</div>
<div id="ref-P3284R4" class="csl-entry" role="doc-biblioentry">
[P3284R4] Eric Niebler.
<code class="sourceCode default">write_env</code> and
<code class="sourceCode default">unstoppable</code> Sender Adaptors. <a href="https://isocpp.org/files/papers/P3284R4.html"><div class="csl-block">https://isocpp.org/files/papers/P3284R4.html</div></a>
</div>
</div>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a href="https://godbolt.org/z/rPEqWz693">https://godbolt.org/z/rPEqWz693</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p><a href="https://gist.github.com/ericniebler/0896776ab1c8f5b7f77d7094c0400df5">https://gist.github.com/ericniebler/0896776ab1c8f5b7f77d7094c0400df5</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
