<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<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-01-12" />
  <title>Diverging Expressions</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>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
td > div > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #C9FBC9;
--diff-strongins: #acf2bd;
--diff-del: #FFC8EB;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
div.std blockquote { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
div.std.ins blockquote {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.ins > div.example {
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3;
}
div.std div.sourceCode { background-color: inherit; margin-left: 1em; }
div.std blockquote del { text-decoration: line-through;
color: #000000; background-color: var(--diff-del);
border: none; }
code del { border: 1px solid #ECB3C7; }
span.orange {
background-color: #ffa500;
}
span.yellow {
background-color: #ffff00;
}</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">Diverging Expressions</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3549R0 <a href="https://wg21.link/P3549">[Latest]</a> <a href="https://wg21.link/P3549/status">[Status]</a></td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-01-12</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>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Bruno Cardoso Lopes<br>&lt;<a href="mailto:bruno.cardoso@gmail.com" class="email">bruno.cardoso@gmail.com</a>&gt;<br>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@gmail.com</a>&gt;<br>
      Michael Park<br>&lt;<a href="mailto:mcypark@gmail.com" class="email">mcypark@gmail.com</a>&gt;<br>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@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="#diverging-expressions" id="toc-diverging-expressions"><span class="toc-section-number">2</span>
Diverging Expressions<span></span></a>
<ul>
<li><a href="#diverging-do-expressions" id="toc-diverging-do-expressions"><span class="toc-section-number">2.1</span> Diverging
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions<span></span></a></li>
<li><a href="#a-bottom-type" id="toc-a-bottom-type"><span class="toc-section-number">2.2</span> A bottom type<span></span></a>
<ul>
<li><a href="#stdfunctionstdnoreturn_t" id="toc-stdfunctionstdnoreturn_t"><span class="toc-section-number">2.2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>function<span class="op">&lt;</span>std<span class="op">::</span>noreturn_t<span class="op">()&gt;</span></code><span></span></a></li>
<li><a href="#stdexpectedt-stdnoreturn_t" id="toc-stdexpectedt-stdnoreturn_t"><span class="toc-section-number">2.2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, std<span class="op">::</span>noreturn_t<span class="op">&gt;</span></code><span></span></a></li>
<li><a href="#valueless-ranges" id="toc-valueless-ranges"><span class="toc-section-number">2.2.3</span> Valueless
Ranges<span></span></a></li>
</ul></li>
<li><a href="#doing-our-due-diligence-to-deduce-do-divergence" id="toc-doing-our-due-diligence-to-deduce-do-divergence"><span class="toc-section-number">2.3</span> Doing Our Due Diligence to Deduce
<code class="sourceCode cpp"><span class="cf">do</span></code>
Divergence<span></span></a></li>
<li><a href="#alternative-with-noreturn" id="toc-alternative-with-noreturn"><span class="toc-section-number">2.4</span> Alternative with <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code><span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">3</span> Proposal<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">4</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">1</span>
Introduction<a href="#introduction" class="self-link"></a></h1>
<p>One pattern that will occur with some regularity with pattern
matching <span class="title"><span class="citation" data-cites="P2688R4"><a href="https://wg21.link/p1771r1" role="doc-biblioref">[P2688R4] (Pattern Matching:
<code class="sourceCode cpp">match</code> Expression)</a></span></span>
(and <span class="title"><span class="citation" data-cites="P2806R2"><a href="https://wg21.link/p2806r2" role="doc-biblioref">[P2806R2] (do
expressions)</a></span></span>) is the desire to produce values for some
patterns but not for all cases. Consider the following simplified
example:</p>
<table>
<tr>
<td>
<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="dt">void</span> f<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> std<span class="op">::</span>terminate<span class="op">()</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
<td>
<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="dt">void</span> g<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>terminate<span class="op">()</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
<td>
<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="dt">void</span> h<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>terminate<span class="op">()</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>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
</tr>
</table>
<p>In all of these cases, the desire is that if <code class="sourceCode cpp">i <span class="op">==</span> <span class="dv">0</span></code>
then we initialize <code class="sourceCode cpp">j</code> to the value
<code class="sourceCode cpp"><span class="dv">0</span></code>, otherwise
we <code class="sourceCode cpp">std<span class="op">::</span>terminate<span class="op">()</span></code>.
Given that <code class="sourceCode cpp">std<span class="op">::</span>terminate</code>
does in fact, as the name suggests, terminate, we don’t actually have to
worry about producing a value in that case. These examples are all
equivalent — or at least, they should be. But C++ does not currently
recognize them as such (with one exception that we’ll get to later).</p>
<p>The rule for pattern matching by default is that the type of the
match expression is deduced from each arm and each arm has to have the
same type. The same rule we have for
<code class="sourceCode cpp"><span class="kw">auto</span></code>
deduction in functions and lambdas. In the above examples, the first arm
always has type
<code class="sourceCode cpp"><span class="dt">int</span></code>. But for
<code class="sourceCode cpp">f<span class="op">()</span></code> and
<code class="sourceCode cpp">g<span class="op">()</span></code>, the
second arm has type
<code class="sourceCode cpp"><span class="dt">void</span></code>. In
order to type check, we have to wrap our call to <code class="sourceCode cpp">std<span class="op">::</span>terminate</code> in
an expression that actually has type
<code class="sourceCode cpp"><span class="dt">int</span></code>. The
<code class="sourceCode cpp"><span class="cf">do</span></code>
expression in
<code class="sourceCode cpp">h<span class="op">()</span></code> is one
such way.</p>
<p>The extra <code class="sourceCode cpp"><span class="op">-&gt;</span> <span class="dt">int</span></code>
does solve the problem, but it’s also misleading. We’re not actually
ever producing an
<code class="sourceCode cpp"><span class="dt">int</span></code> here,
we’re just writing a type annotation to hammer the compiler into
submission. That’s just not a great place to be.</p>
<p>Our goal with this paper is to have all of
<code class="sourceCode cpp">f<span class="op">()</span></code>,
<code class="sourceCode cpp">g<span class="op">()</span></code>, and
<code class="sourceCode cpp">h<span class="op">()</span></code> above
type check. Concretely: we need to recognize that an expression can
<em>diverge</em> and then have pattern matching’s type deduction rules
only consider those arms that do not diverge. Importantly, we want to
treat the expressions:</p>
<div class="std">
<blockquote>
<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>std<span class="op">::</span>terminate<span class="op">()</span></span></code></pre></div>
</blockquote>
</div>
<p>and</p>
<div class="std">
<blockquote>
<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="cf">do</span> <span class="op">{</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>and</p>
<div class="std">
<blockquote>
<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="cf">do</span> <span class="op">{</span> log<span class="op">::</span>error<span class="op">(</span><span class="st">&quot;hasta la vista&quot;</span><span class="op">)</span>; std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>as all being diverging expressions in order to facilitate code
evolution. It would be annoying if a naked call to <code class="sourceCode cpp">std<span class="op">::</span>terminate</code>
worked but once you wrap it in a
<code class="sourceCode cpp"><span class="cf">do</span></code>
expression that does so much as add a single log statement that it
suddenly doesn’t. We want to properly recognize divergence, not just the
most trivial of cases.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="diverging-expressions"><span class="header-section-number">2</span>
Diverging Expressions<a href="#diverging-expressions" class="self-link"></a></h1>
<p>An expression is said to <em>diverge</em> if it unconditionally
escapes control flow. Currently in C++, we have two such expressions in
the language:</p>
<ul>
<li>a <code class="sourceCode cpp"><em>throw-expression</em></code>,
and</li>
<li>a call to a <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
function.</li>
</ul>
<p>The former explicitly diverges (control flow immediately escapes and
doesn’t return to keep evaluating in the original slot) while the latter
implicitly diverges (technically a function marked <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
can still return, we just state that doing so is undefined behavior in
<span>9.12.11 <a href="https://wg21.link/dcl.attr.noreturn">[dcl.attr.noreturn]</a></span>).</p>
<p>As hinted at earlier, the language already recognizes that
expressions can diverge in one spot: the conditional operator.
Consider:</p>
<div class="std">
<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="dt">int</span> x <span class="op">=</span> <em>condition</em> <span class="op">?</span> <span class="dv">42</span> <span class="op">:</span> <span class="cf">throw</span> std<span class="op">::</span>runtime_error<span class="op">(</span><span class="st">&quot;oops&quot;</span><span class="op">)</span>; <span class="co">// OK</span></span></code></pre></div>
</blockquote>
</div>
<p>The conditional operator has to merge two values into one. But if one
of the operands is a
<code class="sourceCode cpp"><em>throw-expression</em></code>, then the
value of the conditional operator is trivially the other operand — or
there is just no value to speak of. The above is perfectly valid code,
the conditional expression is a prvalue
<code class="sourceCode cpp"><span class="dt">int</span></code> (that
sometimes throws).</p>
<p>The pattern matching paper recognizes this as well, and explicitly
recognizes pattern arms that are
<code class="sourceCode cpp"><em>throw-expression</em></code>s as not
participating in deduction either:</p>
<div class="std">
<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="dt">int</span> x <span class="op">=</span> v match <span class="op">{</span> <span class="co">// OK</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  _ <span class="op">=&gt;</span> <span class="cf">throw</span> std<span class="op">::</span>runtime_error<span class="op">(</span><span class="st">&quot;oops&quot;</span><span class="op">)</span>;</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
</div>
<p>But this does not work today, despite being just as diverging as a
<code class="sourceCode cpp"><span class="cf">throw</span></code>:</p>
<div class="std">
<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="dt">int</span> x <span class="op">=</span> <em>condition</em> <span class="op">?</span> <span class="dv">42</span> <span class="op">:</span> std<span class="op">::</span>terminate<span class="op">()</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Instead you could do something like this (which we think is the kind
of thing that really belongs on a T-shirt):</p>
<div class="std">
<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="dt">int</span> x <span class="op">=</span> <em>condition</em> <span class="op">?</span> <span class="dv">42</span> <span class="op">:</span> <span class="cf">throw</span> <span class="op">(</span>std<span class="op">::</span>terminate<span class="op">()</span>, <span class="dv">0</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</div>
<p>Note that this <em>does</em> work — we will terminate before we
evaluate the
<code class="sourceCode cpp"><span class="cf">throw</span></code>.</p>
<p>But there’s not any difference between throwing an exception and
invoking a non-returning function when we’re talking about whether an
expression produces a value. Neither produces a value, so neither needs
to participate in any language rules that involve merging multiple
expressions!</p>
<p>We think it’s important to recognize invocations of non-returning
functions as diverging because we want people to be able to write the
code on the left, and not have to write either of the two workarounds
presented:</p>
<table>
<tr>
<th>
Desired</ht>
<th>
Workaround with
<code class="sourceCode cpp"><span class="cf">throw</span></code>
</th>
<th>
Workaround with explicit type
</th>
</tr>
<tr>
<td>
<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="dt">void</span> f<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> std<span class="op">::</span>terminate<span class="op">()</span>;</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
<td>
<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="dt">void</span> g<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="cf">throw</span> <span class="op">(</span>std<span class="op">::</span>terminate<span class="op">()</span>, <span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
<td>
<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="dt">void</span> h<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> j <span class="op">=</span> i match <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="dv">0</span> <span class="op">=&gt;</span> <span class="dv">0</span>;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    _ <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">-&gt;</span> <span class="dt">int</span> <span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>terminate<span class="op">()</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  use<span class="op">(</span>j<span class="op">)</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</td>
</tr>
</table>
<h2 data-number="2.1" id="diverging-do-expressions"><span class="header-section-number">2.1</span> Diverging
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions<a href="#diverging-do-expressions" class="self-link"></a></h2>
<p>Consider the following expressions:</p>
<ol type="1">
<li><code class="sourceCode cpp"><span class="cf">throw</span> <span class="dv">42</span></code></li>
<li><code class="sourceCode cpp">std<span class="op">::</span>terminate<span class="op">()</span></code></li>
<li><code class="sourceCode cpp"><span class="cf">do</span> <span class="op">{</span> <span class="cf">throw</span> <span class="dv">42</span>; <span class="op">}</span></code></li>
<li><code class="sourceCode cpp"><span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span></code></li>
</ol>
<p>All four of these expressions diverge, the bottom two just trivially
wrap the top two. So we’d want these to have the same properties when it
comes to divergence — otherwise any slight refactoring could have too
much impact. For instance, the desire to change:</p>
<div class="std">
<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>std<span class="op">::</span>terminate<span class="op">()</span></span></code></pre></div>
</blockquote>
</div>
<p>into</p>
<div class="std">
<blockquote>
<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="cf">do</span> <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    log<span class="op">::</span>fatal<span class="op">(</span><span class="st">&quot;oops, I did it again&quot;</span><span class="op">)</span>;</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>terminate<span class="op">()</span>;</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>should ideally not change any properties of the expression. Both
diverge, one just additionally adds some logging.</p>
<p>One question we have to answer is: What is the
<code class="sourceCode cpp"><span class="kw">decltype</span></code> of
such an expression?</p>
<p>Right now, <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="cf">throw</span> <span class="dv">42</span><span class="op">)</span></code>
is defined as
<code class="sourceCode cpp"><span class="dt">void</span></code>, <a href="https://eel.is/c++draft/expr.throw#1">explicitly</a>. For some
reason. <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>terminate<span class="op">())</span></code>
is more obviously
<code class="sourceCode cpp"><span class="dt">void</span></code> simply
because that’s how the function is defined — it is a <code class="sourceCode cpp"><span class="dt">void</span><span class="op">()</span></code>
(although a <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
one). So there’s certainly something to be said for going ahead and
wanting to define <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="cf">do</span> <span class="op">{</span> <span class="cf">throw</span> <span class="dv">42</span>; <span class="op">})</span></code>
as <code class="sourceCode cpp"><span class="dt">void</span></code> as
well.</p>
<p>This approach leads to the following pair of rules:</p>
<ol type="1">
<li>the <em>type</em> of a
<code class="sourceCode cpp"><span class="cf">do</span></code>
expression is either
<ul>
<li>the <em>trailing-return-type</em>, if one is explicitly provided,
or</li>
<li>the type that is
<code class="sourceCode cpp"><span class="kw">do_return</span></code>-ed
consistently (same as the lambda rule except with
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
instead of
<code class="sourceCode cpp"><span class="cf">return</span></code>).</li>
</ul></li>
<li>A <code class="sourceCode cpp"><span class="cf">do</span></code>
expression is said to <em>diverge</em> if every control flow path leads
to executing a diverging expression (i.e. a
<code class="sourceCode cpp"><em>throw-expression</em></code>, a call to
a <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
function, or evaluating another such diverging expression).</li>
</ol>
<p>This effectively means that we keep adding properties to expressions:
an expression would have a type, a value category, whether it’s a
bit-field, and now also whether it diverges.</p>
<p>There is another approach though.</p>
<h2 data-number="2.2" id="a-bottom-type"><span class="header-section-number">2.2</span> A bottom type<a href="#a-bottom-type" class="self-link"></a></h2>
<p>Several languages have a notion of a bottom type
(<code class="sourceCode cpp">⊥</code>) for diverging expressions. This
type is spelled <code class="sourceCode cpp">Nothing</code> in Scala,
<code class="sourceCode cpp">never</code> in TypeScript,
<code class="sourceCode cpp">Never</code> in Python,
<code class="sourceCode cpp">noreturn</code> in D,
<code class="sourceCode cpp"><span class="op">!</span></code> in Rust,
<code class="sourceCode cpp"><span class="dt">void</span></code> in
Haskell (but notably not
<code class="sourceCode cpp"><span class="dt">void</span></code> in
C++), etc. This type represents an expression that diverges.</p>
<p>Let’s imagine what it would look like if C++ also had such a type.
We’ll call it <code class="sourceCode cpp">noreturn_t</code>. It would
some interesting properties:</p>
<ul>
<li>You cannot produce an instance of such a type. It wouldn’t be very
divergent otherwise! In this case, it’s not just that this type isn’t
constructible, but we would also have to eliminate all of C++’s other
clever ways of producing a value (like <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>bit_cast</code>,
etc.).</li>
<li>On the other hand, <code class="sourceCode cpp">noreturn_t</code> is
convertible to any other type (including reference types). This is
currently impossible to emulate in C++ today, since you cannot make a
type that is both convertible to <code class="sourceCode cpp">T</code>
and <code class="sourceCode cpp">T<span class="op">&amp;</span></code>
for all <code class="sourceCode cpp">T</code>.</li>
<li>Function pointer conversions are more interesting. From a type
theory perspective, <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">(*)(</span>T<span class="op">)</span> <span class="op">-&gt;</span> noreturn_t</code>
is convertible to <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">(*)(</span>T<span class="op">)</span> <span class="op">-&gt;</span> U</code>
for all <code class="sourceCode cpp">U</code>. For the same reason
Haskell has the <a href="https://hackage.haskell.org/package/void-0.7/docs/Data-Void.html"><code class="sourceCode cpp">absurd</code>
function</a>. But this doesn’t quite work out in C++ because of calling
convention reasons. Nevertheless, a function pointer that is a constant
expression of type <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">(*)(</span>Args<span class="op">...)</span> <span class="op">-&gt;</span> noreturn_t</code>
can be converted to an <code class="sourceCode cpp"><span class="kw">auto</span><span class="op">(*)(</span>Args<span class="op">...)</span> <span class="op">-&gt;</span> U</code>.
As if this conversion were
<code class="sourceCode cpp"><span class="kw">consteval</span></code>.</li>
</ul>
<p>This makes sense from a type-theoretic perspective and makes a lot of
other uses just work.</p>
<p>We would then change the type of a
<code class="sourceCode cpp"><em>throw-expression</em></code> to be
<code class="sourceCode cpp">noreturn_t</code> (instead of
<code class="sourceCode cpp"><span class="dt">void</span></code>). This
change, coupled with the conversion rule above, means we’d no longer
need the special case in conditional expressions. Consider:</p>
<div class="std">
<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><em>condition</em> <span class="op">?</span> <span class="dv">42</span> <span class="op">:</span> <span class="cf">throw</span> std<span class="op">::</span>runtime_error<span class="op">(</span><span class="st">&quot;oops&quot;</span><span class="op">)</span></span></code></pre></div>
</blockquote>
</div>
<p>The types of the second and third operand are
<code class="sourceCode cpp"><span class="dt">int</span></code> and
<code class="sourceCode cpp">noreturn_t</code>, respectively.
<code class="sourceCode cpp">noreturn_t</code> is convertible to
<code class="sourceCode cpp"><span class="dt">int</span></code> (because
it is convertible to anything), but
<code class="sourceCode cpp"><span class="dt">int</span></code> is not
convertible to <code class="sourceCode cpp">noreturn_t</code> (since
nothing is), thus the result of the expression has type
<code class="sourceCode cpp"><span class="dt">int</span></code>, as
desired.</p>
<p>We would also want to change the signatures of all of our
never-returning functions to have this in their types:</p>
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb17"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>namespace std {</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="st">- [[noreturn]] auto terminate() -&gt; void;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="va">+              auto terminate() -&gt; noreturn_t;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
</blockquote>
</div>
<p>Which would likewise allow for the desired conditional with <code class="sourceCode cpp">std<span class="op">::</span>terminate<span class="op">()</span></code>
to work for the same reasons as the conditional with
<code class="sourceCode cpp"><span class="cf">throw</span></code>:</p>
<div class="std">
<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><em>condition</em> <span class="op">?</span> <span class="dv">42</span> <span class="op">:</span> std<span class="op">::</span>terminate<span class="op">()</span></span></code></pre></div>
</blockquote>
</div>
<p>We’re approaching <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code>
from the perspective of wanting to detect diverging expressions and
statements. But there are other reasons to want to have a bottom type in
the type system. Consider…</p>
<h3 data-number="2.2.1" id="stdfunctionstdnoreturn_t"><span class="header-section-number">2.2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>function<span class="op">&lt;</span>std<span class="op">::</span>noreturn_t<span class="op">()&gt;</span></code><a href="#stdfunctionstdnoreturn_t" class="self-link"></a></h3>
<p>How do you have a callback that signals that it must not terminate?
Well, you can’t really. Because that’s not something you can signal in
the type system today. But with a bottom type it can be, and the type
<code class="sourceCode cpp">std<span class="op">::</span>function<span class="op">&lt;</span>std<span class="op">::</span>noreturn_t<span class="op">()&gt;</span></code>
becomes meaningful.</p>
<h3 data-number="2.2.2" id="stdexpectedt-stdnoreturn_t"><span class="header-section-number">2.2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, std<span class="op">::</span>noreturn_t<span class="op">&gt;</span></code><a href="#stdexpectedt-stdnoreturn_t" class="self-link"></a></h3>
<p>One is its use in sum types. Consider the type <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, std<span class="op">::</span>noreturn_t<span class="op">&gt;</span></code>.
What are its properties? Well, in general, a <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
is holding either a <code class="sourceCode cpp">T</code> in its valid
state or an <code class="sourceCode cpp">E</code> in its error state,
and so it’s storage is something like a
<code class="sourceCode cpp"><span class="dt">bool</span></code> and a
<code class="sourceCode cpp"><span class="kw">union</span> <span class="op">{</span> T; E; <span class="op">}</span></code>.
But if <code class="sourceCode cpp">E</code> is <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code>,
then we know that there <em>cannot be</em> an error state. You cannot
form a value of type <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code>,
so we don’t even need to store it at all. The layout of <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, std<span class="op">::</span>noreturn_t<span class="op">&gt;</span></code>
can simply be <code class="sourceCode cpp"><span class="kw">struct</span> <span class="op">{</span> T; <span class="op">}</span></code>.
Likewise for <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>std<span class="op">::</span>noreturn_t, E<span class="op">&gt;</span></code>,
which can only ever be in the error state.</p>
<p>This is a useful thing to be able to express in the type system,
since you might have an API whose contract is that it returns some kind
of <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, E<span class="op">&gt;</span></code>
— but this particular implementation of that API might simply never fail
(or always fail). So we can return an <code class="sourceCode cpp">expected<span class="op">&lt;</span>T, noreturn_t<span class="op">&gt;</span></code>
to conform to the expected shape of the return type while also having
all the state checks trivially optimize away (since its <code class="sourceCode cpp"><span class="kw">operator</span> <span class="dt">bool</span><span class="op">()</span> <span class="kw">const</span></code>
is trivially just <code class="sourceCode cpp"><span class="cf">return</span> <span class="kw">true</span>;</code>).
Moreover, a lot of code that expects a particular
<code class="sourceCode cpp">E</code> will continue to work fine since
<code class="sourceCode cpp">noreturn_t</code> is convertible to
<code class="sourceCode cpp">E</code>.</p>
<h3 data-number="2.2.3" id="valueless-ranges"><span class="header-section-number">2.2.3</span> Valueless Ranges<a href="#valueless-ranges" class="self-link"></a></h3>
<p>By some coincidence, Barry just ran into this issue (again) while we
were writing the initial revision of this paper.</p>
<p>A Range (in the C++20 sense) has a few associated types. Its
<code class="sourceCode cpp">reference</code> is just <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(*</span>it<span class="op">)</span></code>,
unfortunately named in retrospect since it need not be a reference type.
Then, a range has a <code class="sourceCode cpp">value_type</code> —
which is the type you would use if you wanted an independent value. And
the range’s <code class="sourceCode cpp">value_type</code> and
<code class="sourceCode cpp">reference</code> have to be related
somehow, they need to have a
<code class="sourceCode cpp">common_reference</code>. For most ranges,
there isn’t much to think about here —
<code class="sourceCode cpp">reference</code> is either
<code class="sourceCode cpp">T<span class="op">&amp;</span></code> or
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
for some object type <code class="sourceCode cpp">T</code>,
<code class="sourceCode cpp">value_type</code> is
<code class="sourceCode cpp">T</code>, everything just falls out
straightforwardly.</p>
<p>But there are few situations where this just doesn’t work out:</p>
<ol type="1">
<li><p>Let’s say we have an abstract base class,
<code class="sourceCode cpp">Abstract</code>. We can produce a range
whose <code class="sourceCode cpp">reference</code> is <code class="sourceCode cpp">Abstract<span class="op">&amp;</span></code>
(let’s say we don’t want to deal with pointers, since we know none of
ours are ever null). But we simply <em>cannot</em> produce a
<code class="sourceCode cpp">value_type</code> of
<code class="sourceCode cpp">Abstract</code>. It’s… abstract. There are
situations where you can get away with it, but in a lot of ranges code,
you just can’t. This is <span class="citation" data-cites="LWG3864"><a href="https://wg21.link/lwg3864" role="doc-biblioref">[LWG3864]</a></span>.</p></li>
<li><p>Let’s say we have a type <code class="sourceCode cpp">S</code>
with a trailing flexible array member. We can produce a range whose
reference is
<code class="sourceCode cpp">S<span class="op">&amp;</span></code>.
Unlike <code class="sourceCode cpp">Abstract</code>, it might be valid
to form an object of type <code class="sourceCode cpp">S</code> — it
would just be semantically wrong to do so. Moreover,
<code class="sourceCode cpp">enumerate</code>ing such a range would end
up producing a <code class="sourceCode cpp">value_type</code> of <code class="sourceCode cpp">tuple<span class="op">&lt;</span><span class="dt">ptrdiff_t</span>, S<span class="op">&gt;</span></code>,
which in libstdc++’s layout is <code class="sourceCode cpp"><span class="kw">struct</span> <span class="op">{</span> S; <span class="dt">ptrdiff_t</span>; <span class="op">}</span></code>.
That puts the flexible array member in the middle of the struct, and gcc
14 starts rejecting this code.</p></li>
<li><p>Similar to (2), there are other cases of dynamically sized
ranges. For instance, rather than a <code class="sourceCode cpp">span<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
I might want to produce an <code class="sourceCode cpp">erased_span<span class="op">&lt;</span>Base<span class="op">&gt;</span></code>
which is a range of
<code class="sourceCode cpp">Base<span class="op">&amp;</span></code>
but whose dynamic type (and size) is chosen at runtime. Any code that
attempts to actually produce a
<code class="sourceCode cpp">value_type</code> of
<code class="sourceCode cpp">Base</code> would be logically wrong — even
if it might compile.</p></li>
</ol>
<p>In all of these cases, what we really want to be able to say is:
there <em>is</em> no <code class="sourceCode cpp">value_type</code>. Any
algorithm that attempts to produce one is broken.</p>
<p>A bottom type solves this quite nicely. Adding <code class="sourceCode cpp"><span class="kw">using</span> value_type <span class="op">=</span> std<span class="op">::</span>noreturn_t;</code>
meets the other requirements, as long as <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t<span class="op">&amp;</span></code>
is convertible to <code class="sourceCode cpp">reference</code>. We get
a valid C++20 range and the compile errors we get are actual logic
errors — using algorithms that try to actually form a
<code class="sourceCode cpp">value_type</code>.</p>
<p>This, in of itself, isn’t a complete solution, since all the
invocation concepts in Ranges (<span>24.3.6 <a href="https://wg21.link/indirectcallable">[indirectcallable]</a></span>])
still will attempt to invoke the provided callable with <code class="sourceCode cpp">value_type<span class="op">&amp;</span></code>
(or the projected <code class="sourceCode cpp">value_type<span class="op">&amp;</span></code>),
and we’d need to do something there too. But simply having a <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code> to
use here does solve a lot of the problem.</p>
<h2 data-number="2.3" id="doing-our-due-diligence-to-deduce-do-divergence"><span class="header-section-number">2.3</span> Doing Our Due Diligence to
Deduce <code class="sourceCode cpp"><span class="cf">do</span></code>
Divergence<a href="#doing-our-due-diligence-to-deduce-do-divergence" class="self-link"></a></h2>
<p>Consider the following pattern arms:</p>
<div class="std">
<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><em>pattern</em><sub>1</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna give you up&quot;</span><span class="op">)</span>; <span class="cf">throw</span> <span class="dv">2</span>; <span class="op">}</span>;</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>2</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna let you down&quot;</span><span class="op">)</span>; std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>3</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna run around&quot;</span><span class="op">)</span>; <span class="kw">do_return</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>4</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;and desert you&quot;</span><span class="op">)</span>; <span class="cf">continue</span>; <span class="op">}</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>5</sub> <span class="op">=&gt;</span> <span class="cf">break</span>;</span></code></pre></div>
</blockquote>
</div>
<p>The last case here is simple — we can special case escaping
statements, and the pattern matching paper already does this.</p>
<p>The first four cases though also all unconditionally diverge. We know
that from simply examining the code. But what is the specific language
rule by which we could ensure that the pattern match expression can
exclude these arms when deducing the type? In
<code class="sourceCode cpp"><em>pattern</em><sub>3</sub></code>, we
actually have a
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
statement, so the
<code class="sourceCode cpp"><span class="cf">do</span></code>
expression there could straightforwardly be said to have type
<code class="sourceCode cpp">noreturn_t</code> and thus diverge. But the
other three have no
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
and thus would, by default, end up having type
<code class="sourceCode cpp"><span class="dt">void</span></code> — which
we do not want. So what do we do?</p>
<p>One option is to copy the logic from some other languages (like Rust)
and also the initial GCC statement-expression model and have an implicit
value from
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions. That is, the other three patterns above implicitly take
their values from <code class="sourceCode cpp"><span class="cf">throw</span> <span class="dv">2</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>terminate<span class="op">()</span></code>,
and <code class="sourceCode cpp"><span class="cf">continue</span></code>
respectively — which all have type
<code class="sourceCode cpp">noreturn_t</code>. So this just works. But
the reason we didn’t initially want to do this for
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions was that we don’t already have a way to turn
<code class="sourceCode cpp"><span class="cf">if</span></code>
statements and
<code class="sourceCode cpp"><span class="cf">for</span></code>/<code class="sourceCode cpp"><span class="cf">while</span></code>
statements into expressions — which makes early returns challenging.
From the gcc doc example:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>gcc</strong>
</div></th>
<th><div style="text-align:center">
<strong>Proposed</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="op">({</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> foo<span class="op">()</span>;</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> z;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>y <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> z <span class="op">=</span> y;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span> z <span class="op">=</span> <span class="op">-</span>y;</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    z;</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="op">})</span></span></code></pre></div>

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

<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> foo<span class="op">()</span>;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>y <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do_return</span> y;</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do_return</span> <span class="op">-</span>y;</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>With implicit last value (or, furthermore, with an
<code class="sourceCode cpp"><span class="cf">if</span></code>
expression which operates under implicit last value rules):</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Explicit
<code class="sourceCode cpp"><span class="kw">do_return</span></code></strong>
</div></th>
<th><div style="text-align:center">
<strong>Implicit last value</strong>
</div></th>
<th><div style="text-align:center">
<strong>An
<code class="sourceCode cpp"><span class="cf">if</span></code>
expression</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> foo<span class="op">()</span>;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>y <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do_return</span> y;</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do_return</span> <span class="op">-</span>y;</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> foo<span class="op">()</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>y <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">do_return</span> y;</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">-</span>y;</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> y <span class="op">=</span> foo<span class="op">()</span>;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>y <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>        y;</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>        <span class="op">-</span>y;</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>But we’re concerned that the mixing and matching of explicit and
implicit yields would be confusing. It’s easy to miss the implicit
<code class="sourceCode cpp"><span class="kw">do_return</span></code> in
the presence of explicit ones. Likewise, attempting to turn
<code class="sourceCode cpp"><span class="cf">if</span></code> into an
expression this late in C++’s lifetime might be too novel? We would also
then have to find a way to turn loops into expressions (or resurface
<code class="sourceCode cpp"><span class="kw">do_return</span></code>,
again running into the explicit/implicit issue).</p>
<p>So if we don’t want to use implicit last value, how else can we
deduce divergence? We suggest the following rule, inspired by implicit
last value:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">1</a></span>
An expression is a <em>diverging expression</em> if its type is
<code class="sourceCode cpp">noreturn_t</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">2</a></span>
A <code class="sourceCode cpp"><em>statement</em></code> is a
<em>diverging statement</em> if it is:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(2.1)</a></span>
A <code class="sourceCode cpp"><em>compound-statement</em></code> where
the last statement is a diverging statement,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">(2.2)</a></span>
an <code class="sourceCode cpp"><em>escape-statement</em></code>, <span class="drafnote">See <span class="citation" data-cites="P2688R4"><a href="https://wg21.link/p1771r1" role="doc-biblioref">[P2688R4]</a></span></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">(2.3)</a></span>
a <code class="sourceCode cpp"><em>statement-expression</em></code>
whose <code class="sourceCode cpp"><em>expression</em></code> is a
diverging expression, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(2.4)</a></span>
an <code class="sourceCode cpp"><span class="cf">if</span></code>
statement with an
<code class="sourceCode cpp"><span class="cf">else</span></code> branch,
where both substatements are diverging statements.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(2.5)</a></span>
a constexpr
<code class="sourceCode cpp"><span class="cf">if</span></code> statement
where the taken substatement is a diverging statement.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">3</a></span>
The type of a <code class="sourceCode cpp"><em>do-expression</em></code>
is determined as follows.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">(3.1)</a></span>
If there is a
<code class="sourceCode cpp"><em>trailing-return-type</em></code> that
is not a placeholder, that type.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(3.2)</a></span>
Otherwise, if there are any non-discard
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
statements within the body of the
<code class="sourceCode cpp"><em>do-expression</em></code>, let
<code class="sourceCode cpp">T</code> be the type deduced from them. If
the type deduced is not the same in each deduction, the program is
ill-formed. Otherwise, the type is
<code class="sourceCode cpp">T</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(3.3)</a></span>
Otherwise, if the last
<code class="sourceCode cpp"><em>statement</em></code> is a diverging
statement, then <code class="sourceCode cpp">noreturn_t</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">(3.4)</a></span>
Otherwise,
<code class="sourceCode cpp"><span class="dt">void</span></code>.</li>
</ul>
</blockquote>
</div>
<p>If there are any
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
statements, then the
<code class="sourceCode cpp"><span class="cf">do</span></code>
expression doesn’t diverge. It might produce a value. Maybe that
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
statement is logically unreachable, but we can’t in general determine
that. But if there are no
<code class="sourceCode cpp"><span class="kw">do_return</span></code>
statements, we need to see if we actually diverge. Which is non-trivial
because we need to handle things like:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="co">// just an escaping-statement</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span> <span class="cf">continue</span>; <span class="op">}</span></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><span class="co">// a statement-expression that is a diverging expression</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a><span class="co">// an if statement with just an if, this is NOT diverging</span></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a><span class="co">// because if the <em>condition</em> is false, then we&#39;re just a void expression</span></span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span> <span class="cf">if</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span> <span class="cf">throw</span> <span class="dv">1</span>; <span class="op">}</span> <span class="op">}</span></span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a><span class="co">// but this one DOES diverge (just differently in both branches)</span></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span> <span class="cf">if</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span> <span class="cf">continue</span>; <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span> <span class="cf">break</span>; <span class="op">}</span> <span class="op">}</span></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a><span class="co">// this diverges if the condition is true</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a><span class="cf">do</span> <span class="op">{</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>condition</em><span class="op">)</span> <span class="op">{</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span> <span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>This rule ensures that all of our initial pattern arms diverge, as
desired:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>1</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna make you cry&quot;</span><span class="op">)</span>; <span class="cf">throw</span> <span class="dv">2</span>; <span class="op">}</span>;</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>2</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna say goodbye&quot;</span><span class="op">)</span>; std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>3</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;never gonna tell a lie&quot;</span><span class="op">)</span>; <span class="kw">do_return</span> std<span class="op">::</span>terminate<span class="op">()</span>; <span class="op">}</span>;</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>4</sub> <span class="op">=&gt;</span> <span class="cf">do</span> <span class="op">{</span> std<span class="op">::</span>println<span class="op">(</span><span class="st">&quot;and hurt you&quot;</span><span class="op">)</span>; <span class="cf">continue</span>; <span class="op">}</span>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><em>pattern</em><sub>5</sub> <span class="op">=&gt;</span> <span class="cf">break</span>;</span></code></pre></div>
</blockquote>
</div>
<h2 data-number="2.4" id="alternative-with-noreturn"><span class="header-section-number">2.4</span> Alternative with <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code><a href="#alternative-with-noreturn" class="self-link"></a></h2>
<p>The advantage of the approach described with
<code class="sourceCode cpp">noreturn_t</code> is that diverging
expressions can appear in the type system. This provides a better
solution than <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>,
in a way that can further generalize to other scenarios (as we showed
earlier). We can have a <code class="sourceCode cpp">std<span class="op">::</span>function<span class="op">&lt;</span>std<span class="op">::</span>noreturn_t<span class="op">()&gt;</span></code>,
we can have <code class="sourceCode cpp">std<span class="op">::</span>expected<span class="op">&lt;</span>T, std<span class="op">::</span>noreturn_t<span class="op">&gt;</span></code>,
valueless ranges, etc.</p>
<p>But an alternative approach would be to avoid changing any of the
existing functions (like <code class="sourceCode cpp">std<span class="op">::</span>abort<span class="op">()</span></code>,
<code class="sourceCode cpp">std<span class="op">::</span>terminate<span class="op">()</span></code>,
etc.) or changing the type of a
<code class="sourceCode cpp"><em>throw-expression</em></code>, and
instead recognize <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
more explicitly.</p>
<p>The rule we lay out above would instead become:</p>
<div class="std">
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">1</a></span>
A <code class="sourceCode cpp"><em>statement</em></code> is a
<em>diverging statement</em> if it is:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(1.1)</a></span>
A <code class="sourceCode cpp"><em>compound-statement</em></code> where
the last statement is a diverging statement,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(1.2)</a></span>
an <code class="sourceCode cpp"><em>escaping-statement</em></code>,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(1.3)</a></span>
a <code class="sourceCode cpp"><em>statement-expression</em></code>
whose <code class="sourceCode cpp"><em>expression</em></code> is a
diverging expression, or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">(1.4)</a></span>
an <code class="sourceCode cpp"><span class="cf">if</span></code>
statement with an
<code class="sourceCode cpp"><span class="cf">else</span></code> branch,
where both substatements are diverging statements.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(1.5)</a></span>
a constexpr
<code class="sourceCode cpp"><span class="cf">if</span></code> statement
where the taken substatement is a diverging statement.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">2</a></span>
An expression is a <em>diverging expression</em> if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">(2.1)</a></span>
it is an invocation of a <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
function,</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">(2.2)</a></span>
it is a <code class="sourceCode cpp"><em>throw-expression</em></code>,
or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">(2.3)</a></span>
it is a <code class="sourceCode cpp"><em>do-expression</em></code> whose
type is <code class="sourceCode cpp"><span class="dt">void</span></code>
and whose last statement is a diverging statement.</li>
</ul>
</blockquote>
</div>
<p>This is a simpler change. It doesn’t involve introducing a new
language/library type or changing existing standard library functions or
the meanings of some code — although we doubt too many people are
relying on <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="cf">throw</span> <span class="dv">1</span><span class="op">)</span></code>
being <code class="sourceCode cpp"><span class="dt">void</span></code>.
However, it doesn’t compose. <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
isn’t deduced, so wrapping becomes challenging.</p>
<p>Leaning on <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span></code>
also means that we end up leaning on
<code class="sourceCode cpp"><span class="dt">void</span></code> even
harder to mean two completely different things: <code class="sourceCode cpp"><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span> <span class="op">}</span></code>
is a function that returns a value, while <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span> <span class="dt">void</span> g<span class="op">()</span> <span class="op">{</span> std<span class="op">::</span>exit<span class="op">(-</span><span class="dv">1</span><span class="op">)</span>; <span class="op">}</span></code>
is a function that doesn’t.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>We propose to:</p>
<ul>
<li>to introduce a new type <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code>
which represents an expression with no value, that unconditionally
diverges.
<ul>
<li><code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code> is
convertible to any type (include reference types)</li>
<li><code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code> is
not constructible, and you cannot <code class="sourceCode cpp"><span class="kw">reinterpret_cast</span></code>
into it, <code class="sourceCode cpp">std<span class="op">::</span>bit_cast</code> into
it,
<code class="sourceCode cpp"><span class="kw">static_cast</span></code>
into it, etc.</li>
<li><code class="sourceCode cpp">std<span class="op">::</span>noreturn_t<span class="op">(*)(</span>Args<span class="op">...)</span></code>
is convertible to <code class="sourceCode cpp">R<span class="op">(*)(</span>Args<span class="op">...)</span></code>
for all <code class="sourceCode cpp">R</code> (again, including
reference types), but only if the source function pointer is a constant
expression (i.e. this conversion behaves as if it is a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
function).</li>
</ul></li>
<li>change all the standard library functions that are currently <code class="sourceCode cpp"><span class="op">[[</span><span class="at">noreturn</span><span class="op">]]</span> <span class="dt">void</span> f<span class="op">()</span></code>
to instead be <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t f<span class="op">()</span></code></li>
<li>change the type of
<code class="sourceCode cpp"><em>throw-expression</em></code> to <code class="sourceCode cpp">std<span class="op">::</span>noreturn_t</code>
and remove the current… uh… exception for exceptions in the conditional
operator (it will be subsumed by the usual convertibility rule).</li>
<li>adopt the same rules for
<code class="sourceCode cpp"><span class="cf">do</span></code>
expressions <span class="citation" data-cites="P2806R2"><a href="https://wg21.link/p2806r2" role="doc-biblioref">[P2806R2]</a></span>.</li>
</ul>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">4</span>
References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-LWG3864" class="csl-entry" role="doc-biblioentry">
[LWG3864] Barry Revzin. zip over range of reference to an abstract type.
<a href="https://wg21.link/lwg3864"><div class="csl-block">https://wg21.link/lwg3864</div></a>
</div>
<div id="ref-P2688R4" class="csl-entry" role="doc-biblioentry">
[P2688R4] Michael Park. 2024-12-17. Pattern Matching:
<code class="sourceCode cpp">match</code> Expression. <a href="https://wg21.link/p1771r1"><div class="csl-block">https://wg21.link/p1771r1</div></a>
</div>
<div id="ref-P2806R2" class="csl-entry" role="doc-biblioentry">
[P2806R2] Barry Revzin, Bruno Cardoso Lopez, Zach Laine, Michael Park.
2023-11-16. do expressions. <a href="https://wg21.link/p2806r2"><div class="csl-block">https://wg21.link/p2806r2</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
